From 8f8d76862bd867b614c667c5b1b48ced09899b52 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Mon, 1 Dec 2025 14:46:46 -0500 Subject: [PATCH 01/43] add chat to beta --- src/resources/beta/beta.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/resources/beta/beta.ts b/src/resources/beta/beta.ts index 7bbca11a6..4c0528f34 100644 --- a/src/resources/beta/beta.ts +++ b/src/resources/beta/beta.ts @@ -74,6 +74,7 @@ import { TranscriptionSessionUpdatedEvent, } from './realtime/realtime'; import * as ChatKitAPI from './chatkit/chatkit'; +import * as ChatAPI from '../chat/chat'; import { ChatKit, ChatKitWorkflow } from './chatkit/chatkit'; import * as ThreadsAPI from './threads/threads'; import { @@ -98,6 +99,7 @@ export class Beta extends APIResource { chatkit: ChatKitAPI.ChatKit = new ChatKitAPI.ChatKit(this._client); assistants: AssistantsAPI.Assistants = new AssistantsAPI.Assistants(this._client); threads: ThreadsAPI.Threads = new ThreadsAPI.Threads(this._client); + chat: ChatAPI.Chat = new ChatAPI.Chat(this._client); } Beta.Realtime = Realtime; From 1260ec6bde6955066b4df13ce65c73d3d2d1e00a Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Mon, 1 Dec 2025 16:52:39 -0500 Subject: [PATCH 02/43] start adding option for new iterator --- examples/tool-calls-beta-zod.ts | 100 +++++ src/helpers/beta/zod.ts | 72 ++++ src/internal/utils/values.ts | 7 + src/lib/beta-parser.ts | 105 +++++ src/lib/beta/BetaRunnableTool.ts | 10 + src/lib/beta/BetaToolRunner.ts | 397 ++++++++++++++++++ src/lib/transform-json-schema.ts | 124 ++++++ src/resources/chat/completions/completions.ts | 15 + 8 files changed, 830 insertions(+) create mode 100644 examples/tool-calls-beta-zod.ts create mode 100644 src/helpers/beta/zod.ts create mode 100644 src/lib/beta-parser.ts create mode 100644 src/lib/beta/BetaRunnableTool.ts create mode 100644 src/lib/beta/BetaToolRunner.ts create mode 100644 src/lib/transform-json-schema.ts diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts new file mode 100644 index 000000000..db7fb4337 --- /dev/null +++ b/examples/tool-calls-beta-zod.ts @@ -0,0 +1,100 @@ +#!/usr/bin/env -S npm run tsn -T + +import OpenAI from 'openai'; +import { betaZodTool } from 'openai/helpers/beta/zod'; +// import { BetaToolUseBlock } from 'openai/helpers/beta'; +import { z } from 'zod'; + +const client = new OpenAI(); + +async function main() { + const runner = client.beta.chat.completions.toolRunner({ + messages: [ + { + role: 'user', + content: `I'm planning a trip to San Francisco and I need some information. Can you help me with the weather, current time, and currency exchange rates (from EUR)? Please use parallel tool use`, + }, + ], + tools: [ + betaZodTool({ + name: 'getWeather', + description: 'Get the weather at a specific location', + inputSchema: z.object({ + location: z.string().describe('The city and state, e.g. San Francisco, CA'), + }), + run: ({ location }) => { + return `The weather is sunny with a temperature of 20°C in ${location}.`; + }, + }), + betaZodTool({ + name: 'getTime', + description: 'Get the current time in a specific timezone', + inputSchema: z.object({ + timezone: z.string().describe('The timezone, e.g. America/Los_Angeles'), + }), + run: ({ timezone }) => { + return `The current time in ${timezone} is 3:00 PM.`; + }, + }), + betaZodTool({ + name: 'getCurrencyExchangeRate', + description: 'Get the exchange rate between two currencies', + inputSchema: z.object({ + from_currency: z.string().describe('The currency to convert from, e.g. USD'), + to_currency: z.string().describe('The currency to convert to, e.g. EUR'), + }), + run: ({ from_currency, to_currency }) => { + return `The exchange rate from ${from_currency} to ${to_currency} is 0.85.`; + }, + }), + ], + model: 'gpt-4o', + max_tokens: 1024, + // This limits the conversation to at most 10 back and forth between the API. + max_iterations: 10, + }); + + console.log(`\nšŸš€ Running tools...\n`); + + for await (const message of runner) { + console.log(`ā”Œā”€ Message ${message.id} `.padEnd(process.stdout.columns, '─')); + console.log(); + + const { choices } = message; + const firstChoice = choices.at(0)!; + + console.log(`${firstChoice.message.content}\n`); // text + // each tool call (could be many) + for (const toolCall of firstChoice.message.tool_calls ?? []) { + if (toolCall.type === 'function') { + console.log(`${toolCall.function.name}(${JSON.stringify(toolCall.function.arguments, null, 2)})\n`); + } + } + + console.log(`└─`.padEnd(process.stdout.columns, '─')); + console.log(); + console.log(); + + // const defaultResponse = await runner.generateToolResponse(); + // if (defaultResponse && typeof defaultResponse.content !== 'string') { + // console.log(`ā”Œā”€ Response `.padEnd(process.stdout.columns, '─')); + // console.log(); + + // for (const block of defaultResponse.content) { + // if (block.type === 'tool_result') { + // const toolUseBlock = message.content.find((b): b is BetaToolUseBlock => { + // return b.type === 'tool_use' && b.id === block.tool_use_id; + // })!; + // console.log(`${toolUseBlock.name}(): ${block.content}`); + // } + // } + + // console.log(); + // console.log(`└─`.padEnd(process.stdout.columns, '─')); + // console.log(); + // console.log(); + // } + } +} + +main(); diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts new file mode 100644 index 000000000..69ef8f2a4 --- /dev/null +++ b/src/helpers/beta/zod.ts @@ -0,0 +1,72 @@ +import { transformJSONSchema } from '../..//lib/transform-json-schema'; +import type { infer as zodInfer, ZodType } from 'zod'; +import * as z from 'zod'; +import { OpenAIError } from '../../core/error'; +// import { AutoParseableBetaOutputFormat } from '../../lib/beta-parser'; +// import { BetaRunnableTool, Promisable } from '../../lib/tools/BetaRunnableTool'; +// import { BetaToolResultContentBlockParam } from '../../resources/beta'; +/** + * Creates a JSON schema output format object from the given Zod schema. + * + * If this is passed to the `.parse()` method then the response message will contain a + * `.parsed` property that is the result of parsing the content with the given Zod object. + * + * This can be passed directly to the `.create()` method but will not + * result in any automatic parsing, you'll have to parse the response yourself. + */ +export function betaZodOutputFormat( + zodObject: ZodInput, +): AutoParseableBetaOutputFormat> { + let jsonSchema = z.toJSONSchema(zodObject, { reused: 'ref' }); + + jsonSchema = transformJSONSchema(jsonSchema); + + return { + type: 'json_schema', + schema: { + ...jsonSchema, + }, + parse: (content) => { + const output = zodObject.safeParse(JSON.parse(content)); + + if (!output.success) { + throw new OpenAIError( + `Failed to parse structured output: ${output.error.message} cause: ${output.error.issues}`, + ); + } + + return output.data; + }, + }; +} + +/** + * Creates a tool using the provided Zod schema that can be passed + * into the `.toolRunner()` method. The Zod schema will automatically be + * converted into JSON Schema when passed to the API. The provided function's + * input arguments will also be validated against the provided schema. + */ +export function betaZodTool(options: { + name: string; + inputSchema: InputSchema; + description: string; + run: (args: zodInfer) => Promisable>; +}): BetaRunnableTool> { + const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' }); + + if (jsonSchema.type !== 'object') { + throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`); + } + + // TypeScript doesn't narrow the type after the runtime check, so we need to assert it + const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; + + return { + type: 'custom', + name: options.name, + input_schema: objectSchema, + description: options.description, + run: options.run, + parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, + }; +} diff --git a/src/internal/utils/values.ts b/src/internal/utils/values.ts index 284ff5cde..d3bce3e1b 100644 --- a/src/internal/utils/values.ts +++ b/src/internal/utils/values.ts @@ -103,3 +103,10 @@ export const safeJSON = (text: string) => { return undefined; } }; + +// Gets a value from an object, deletes the key, and returns the value (or undefined if not found) +export const pop = , K extends string>(obj: T, key: K): T[K] => { + const value = obj[key]; + delete obj[key]; + return value; +}; diff --git a/src/lib/beta-parser.ts b/src/lib/beta-parser.ts new file mode 100644 index 000000000..d418c9862 --- /dev/null +++ b/src/lib/beta-parser.ts @@ -0,0 +1,105 @@ +import { OpenAIError } from '../core/error'; +import { + BetaContentBlock, + BetaJSONOutputFormat, + BetaMessage, + BetaTextBlock, + MessageCreateParams, +} from '../resources/beta/messages/messages'; + +// vendored from typefest just to make things look a bit nicer on hover +type Simplify = { [KeyType in keyof T]: T[KeyType] } & {}; + +export type BetaParseableMessageCreateParams = Simplify< + Omit & { + output_format?: BetaJSONOutputFormat | AutoParseableBetaOutputFormat | null; + } +>; + +export type ExtractParsedContentFromBetaParams = + Params['output_format'] extends AutoParseableBetaOutputFormat ? P : null; + +export type AutoParseableBetaOutputFormat = BetaJSONOutputFormat & { + parse(content: string): ParsedT; +}; + +export type ParsedBetaMessage = BetaMessage & { + content: Array>; + parsed_output: ParsedT | null; +}; + +export type ParsedBetaContentBlock = + | (BetaTextBlock & { parsed: ParsedT | null }) + | Exclude; + +export function maybeParseBetaMessage( + message: BetaMessage, + params: Params, +): ParsedBetaMessage>> { + if (!params || !('parse' in (params.output_format ?? {}))) { + return { + ...message, + content: message.content.map((block) => { + if (block.type === 'text') { + return { + ...block, + parsed: null, + }; + } + return block; + }), + parsed_output: null, + } as ParsedBetaMessage>>; + } + + return parseBetaMessage(message, params); +} + +export function parseBetaMessage( + message: BetaMessage, + params: Params, +): ParsedBetaMessage> { + let firstParsed: ReturnType> | null = null; + + const content: Array>> = + message.content.map((block) => { + if (block.type === 'text') { + const parsed = parseBetaOutputFormat(params, block.text); + + if (firstParsed === null) { + firstParsed = parsed; + } + + return { + ...block, + parsed, + }; + } + return block; + }); + + return { + ...message, + content, + parsed_output: firstParsed, + } as ParsedBetaMessage>; +} + +function parseBetaOutputFormat( + params: Params, + content: string, +): ExtractParsedContentFromBetaParams | null { + if (params.output_format?.type !== 'json_schema') { + return null; + } + + try { + if ('parse' in params.output_format) { + return params.output_format.parse(content); + } + + return JSON.parse(content); + } catch (error) { + throw new OpenAIError(`Failed to parse structured output: ${error}`); + } +} diff --git a/src/lib/beta/BetaRunnableTool.ts b/src/lib/beta/BetaRunnableTool.ts new file mode 100644 index 000000000..e05a20bc1 --- /dev/null +++ b/src/lib/beta/BetaRunnableTool.ts @@ -0,0 +1,10 @@ +import type { ChatCompletionTool } from '../../resources'; + +export type Promisable = T | Promise; + +// this type is just an extension of BetaTool with a run and parse method +// that will be called by `toolRunner()` helpers +export type BetaRunnableTool = ChatCompletionTool & { + run: (args: Input) => Promisable>; + parse: (content: unknown) => Input; +}; diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts new file mode 100644 index 000000000..0150c84a7 --- /dev/null +++ b/src/lib/beta/BetaToolRunner.ts @@ -0,0 +1,397 @@ +import type { + ChatCompletion, + ChatCompletionCreateParams, + ChatCompletionMessageParam, + ChatCompletionStream, + ChatCompletionTool, + ChatCompletionToolMessageParam, +} from '../../resources/chat/completions'; +import type { OpenAI } from '../..'; +import { OpenAIError } from '../../core/error'; +import type { BetaRunnableTool } from './BetaRunnableTool'; +// BetaMessage, BetaMessageParam, BetaToolUnion, MessageCreateParams +// import { BetaMessageStream } from '../BetaMessageStream'; + +/** + * Just Promise.withResolvers(), which is not available in all environments. + */ +function promiseWithResolvers(): { + promise: Promise; + resolve: (value: T) => void; + reject: (reason?: any) => void; +} { + let resolve: (value: T) => void; + let reject: (reason?: any) => void; + const promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + return { promise, resolve: resolve!, reject: reject! }; +} + +/** + * A ToolRunner handles the automatic conversation loop between the assistant and tools. + * + * A ToolRunner is an async iterable that yields either BetaMessage or BetaMessageStream objects + * depending on the streaming configuration. + */ +export class BetaToolRunner { + /** Whether the async iterator has been consumed */ + #consumed = false; + /** Whether parameters have been mutated since the last API call */ + #mutated = false; + /** Current state containing the request parameters */ + #state: { params: BetaToolRunnerParams }; + /** Promise for the last message received from the assistant */ + #message?: Promise | undefined; + /** Cached tool response to avoid redundant executions */ + #toolResponse?: Promise | undefined; + /** Promise resolvers for waiting on completion */ + #completion: { + promise: Promise; + resolve: (value: ChatCompletion) => void; + reject: (reason?: any) => void; + }; + /** Number of iterations (API requests) made so far */ + #iterationCount = 0; + + constructor( + private client: OpenAI, + params: BetaToolRunnerParams, + ) { + this.#state = { + params: { + // You can't clone the entire params since there are functions as handlers. + // You also don't really need to clone params.messages, but it probably will prevent a foot gun + // somewhere. + ...params, + messages: structuredClone(params.messages), + }, + }; + + this.#completion = promiseWithResolvers(); + } + + async *[Symbol.asyncIterator](): AsyncIterator< + Stream extends true ? + ChatCompletionStream // TODO: for now! + : Stream extends false ? ChatCompletion + : ChatCompletionCreateParams | ChatCompletionCreateParams + > { + if (this.#consumed) { + throw new OpenAIError('Cannot iterate over a consumed stream'); + } + + this.#consumed = true; + this.#mutated = true; + this.#toolResponse = undefined; + + try { + while (true) { + let stream: any; + try { + if ( + this.#state.params.max_iterations && + this.#iterationCount >= this.#state.params.max_iterations + ) { + break; + } + + this.#mutated = false; + this.#message = undefined; + this.#toolResponse = undefined; + this.#iterationCount++; + + const { max_iterations, ...params } = this.#state.params; + if (params.stream) { + throw new Error('TODO'); // TODO + // stream = this.client.beta.chat.completions.stream({ ...params }); + // this.#message = stream.finalMessage(); + // // Make sure that this promise doesn't throw before we get the option to do something about it. + // // Error will be caught when we call await this.#message ultimately + // this.#message.catch(() => {}); + // yield stream as any; + } else { + this.#message = this.client.beta.chat.completions.create({ ...params, stream: false }); + yield this.#message as any; + } + + if (!this.#mutated) { + const { choices } = await this.#message; + const { role, content } = choices[0]!.message; // TODO: ensure there's at least one choice + // this.#state.params.messages.push({ role, content }); TODO: we want to add all + this.#state.params.messages.push({ role, content }); + } + + const toolMessage = await this.#generateToolResponse(this.#state.params.messages.at(-1)!); + if (toolMessage) { + this.#state.params.messages.push(toolMessage); + } + + if (!toolMessage && !this.#mutated) { + break; + } + } finally { + if (stream) { + stream.abort(); + } + } + } + + if (!this.#message) { + throw new OpenAIError('ToolRunner concluded without a message from the server'); + } + + this.#completion.resolve(await this.#message); + } catch (error) { + this.#consumed = false; + // Silence unhandled promise errors + this.#completion.promise.catch(() => {}); + this.#completion.reject(error); + this.#completion = promiseWithResolvers(); + throw error; + } + } + + /** + * Update the parameters for the next API call. This invalidates any cached tool responses. + * + * @param paramsOrMutator - Either new parameters or a function to mutate existing parameters + * + * @example + * // Direct parameter update + * runner.setMessagesParams({ + * model: 'gpt-4o', + * max_tokens: 500, + * }); + * + * @example + * // Using a mutator function + * runner.setMessagesParams((params) => ({ + * ...params, + * max_tokens: 100, + * })); + */ + setMessagesParams(params: BetaToolRunnerParams): void; + setMessagesParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void; + setMessagesParams( + paramsOrMutator: BetaToolRunnerParams | ((prevParams: BetaToolRunnerParams) => BetaToolRunnerParams), + ) { + if (typeof paramsOrMutator === 'function') { + this.#state.params = paramsOrMutator(this.#state.params); + } else { + this.#state.params = paramsOrMutator; + } + this.#mutated = true; + // Invalidate cached tool response since parameters changed + this.#toolResponse = undefined; + } + + /** + * Get the tool response for the last message from the assistant. + * Avoids redundant tool executions by caching results. + * + * @returns A promise that resolves to a BetaMessageParam containing tool results, or null if no tools need to be executed + * + * @example + * const toolResponse = await runner.generateToolResponse(); + * if (toolResponse) { + * console.log('Tool results:', toolResponse.content); + * } + */ + async generateToolResponse() { + const message = (await this.#message) ?? this.params.messages.at(-1); + if (!message) { + return null; + } + // TODO: this cast is probably bad + return this.#generateToolResponse(message as ChatCompletionMessageParam); + } + + async #generateToolResponse(lastMessage: ChatCompletionMessageParam) { + if (this.#toolResponse !== undefined) { + return this.#toolResponse; + } + this.#toolResponse = generateToolResponse(this.#state.params, lastMessage); + return this.#toolResponse; + } + + /** + * Wait for the async iterator to complete. This works even if the async iterator hasn't yet started, and + * will wait for an instance to start and go to completion. + * + * @returns A promise that resolves to the final BetaMessage when the iterator completes + * + * @example + * // Start consuming the iterator + * for await (const message of runner) { + * console.log('Message:', message.content); + * } + * + * // Meanwhile, wait for completion from another part of the code + * const finalMessage = await runner.done(); + * console.log('Final response:', finalMessage.content); + */ + done(): Promise { + return this.#completion.promise; + } + + /** + * Returns a promise indicating that the stream is done. Unlike .done(), this will eagerly read the stream: + * * If the iterator has not been consumed, consume the entire iterator and return the final message from the + * assistant. + * * If the iterator has been consumed, waits for it to complete and returns the final message. + * + * @returns A promise that resolves to the final BetaMessage from the conversation + * @throws {OpenAIError} If no messages were processed during the conversation + * + * @example + * const finalMessage = await runner.runUntilDone(); + * console.log('Final response:', finalMessage.content); + */ + async runUntilDone(): Promise { + // If not yet consumed, start consuming and wait for completion + if (!this.#consumed) { + for await (const _ of this) { + // Iterator naturally populates this.#message + } + } + + // If consumed but not completed, wait for completion + return this.done(); + } + + /** + * Get the current parameters being used by the ToolRunner. + * + * @returns A readonly view of the current ToolRunnerParams + * + * @example + * const currentParams = runner.params; + * console.log('Current model:', currentParams.model); + * console.log('Message count:', currentParams.messages.length); + */ + get params(): Readonly { + return this.#state.params as Readonly; + } + + /** + * Add one or more messages to the conversation history. + * + * @param messages - One or more BetaMessageParam objects to add to the conversation + * + * @example + * runner.pushMessages( + * { role: 'user', content: 'Also, what about the weather in NYC?' } + * ); + * + * @example + * // Adding multiple messages + * runner.pushMessages( + * { role: 'user', content: 'What about NYC?' }, + * { role: 'user', content: 'And Boston?' } + * ); + */ + pushMessages(...messages: ChatCompletionMessageParam[]) { + this.setMessagesParams((params) => ({ + ...params, + messages: [...params.messages, ...messages], + })); + } + + /** + * Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone() + * This allows using `await runner` instead of `await runner.runUntilDone()` + */ + then( + onfulfilled?: ((value: ChatCompletion) => TResult1 | PromiseLike) | undefined | null, + onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, + ): Promise { + return this.runUntilDone().then(onfulfilled, onrejected); + } +} + +async function generateToolResponse( + params: BetaToolRunnerParams, + lastMessage = params.messages.at(-1), +): Promise { + // Only process if the last message is from the assistant and has tool use blocks + if ( + !lastMessage || + lastMessage.role !== 'assistant' || + !lastMessage.tool_calls || + lastMessage.tool_calls.length === 0 + ) { + return null; + } + + const toolUseBlocks = lastMessage.tool_calls.filter((toolCall) => toolCall.type === 'function'); + if (toolUseBlocks.length === 0) { + return null; + } + + const toolResults = await Promise.all( + toolUseBlocks.map(async (toolUse) => { + // TODO: we should be able to infer that toolUseBlocks is FunctionDefinition[] or can cast it (maybe!) + const tool = params.tools.find( + (t) => + ('name' in t && 'function' in t ? t.function.name + : 'name' in t ? t.name + : undefined) === toolUse.function.name, + ); + if (!tool || !('run' in tool)) { + return { + type: 'tool_result' as const, + tool_use_id: toolUse.id, + content: `Error: Tool '${toolUse.function.name}' not found`, + is_error: true, + }; + } + + try { + let input = JSON.parse(toolUse.function.arguments); + if ('parse' in tool && tool.parse) { + input = tool.parse(input); + } + + const result = await tool.run(input); + return { + type: 'tool_result' as const, + tool_use_id: toolUse.id, + content: result, + }; + } catch (error) { + return { + type: 'tool_result' as const, + tool_use_id: toolUse.id, + content: `Error: ${error instanceof Error ? error.message : String(error)}`, + is_error: true, + }; + } + }), + ); + + return { + role: 'tool' as const, + content: JSON.stringify(toolResults), + tool_call_id: toolUseBlocks[0]!.id, + }; +} + +// vendored from typefest just to make things look a bit nicer on hover +type Simplify = { [KeyType in keyof T]: T[KeyType] } & {}; + +/** + * Parameters for creating a ToolRunner, extending MessageCreateParams with runnable tools. + */ +export type BetaToolRunnerParams = Simplify< + Omit & { + tools: (ChatCompletionTool | BetaRunnableTool)[]; + /** + * Maximum number of iterations (API requests) to make in the tool execution loop. + * Each iteration consists of: assistant response → tool execution → tool results. + * When exceeded, the loop will terminate even if tools are still being requested. + */ + max_iterations?: number; + } +>; diff --git a/src/lib/transform-json-schema.ts b/src/lib/transform-json-schema.ts new file mode 100644 index 000000000..b7132bb68 --- /dev/null +++ b/src/lib/transform-json-schema.ts @@ -0,0 +1,124 @@ +import { pop } from '../internal/utils'; + +// Supported string formats +const SUPPORTED_STRING_FORMATS = new Set([ + 'date-time', + 'time', + 'date', + 'duration', + 'email', + 'hostname', + 'uri', + 'ipv4', + 'ipv6', + 'uuid', +]); + +export type JSONSchema = Record; + +function deepClone(obj: T): T { + return JSON.parse(JSON.stringify(obj)); +} + +export function transformJSONSchema(jsonSchema: JSONSchema): JSONSchema { + const workingCopy = deepClone(jsonSchema); + return _transformJSONSchema(workingCopy); +} + +function _transformJSONSchema(jsonSchema: JSONSchema): JSONSchema { + const strictSchema: JSONSchema = {}; + + const ref = pop(jsonSchema, '$ref'); + if (ref !== undefined) { + strictSchema['$ref'] = ref; + return strictSchema; + } + + const defs = pop(jsonSchema, '$defs'); + if (defs !== undefined) { + const strictDefs: Record = {}; + strictSchema['$defs'] = strictDefs; + for (const [name, defSchema] of Object.entries(defs)) { + strictDefs[name] = _transformJSONSchema(defSchema as JSONSchema); + } + } + + const type = pop(jsonSchema, 'type'); + const anyOf = pop(jsonSchema, 'anyOf'); + const oneOf = pop(jsonSchema, 'oneOf'); + const allOf = pop(jsonSchema, 'allOf'); + + if (Array.isArray(anyOf)) { + strictSchema['anyOf'] = anyOf.map((variant) => _transformJSONSchema(variant as JSONSchema)); + } else if (Array.isArray(oneOf)) { + strictSchema['anyOf'] = oneOf.map((variant) => _transformJSONSchema(variant as JSONSchema)); + } else if (Array.isArray(allOf)) { + strictSchema['allOf'] = allOf.map((entry) => _transformJSONSchema(entry as JSONSchema)); + } else { + if (type === undefined) { + throw new Error('JSON schema must have a type defined if anyOf/oneOf/allOf are not used'); + } + strictSchema['type'] = type; + } + + const description = pop(jsonSchema, 'description'); + if (description !== undefined) { + strictSchema['description'] = description; + } + + const title = pop(jsonSchema, 'title'); + if (title !== undefined) { + strictSchema['title'] = title; + } + + if (type === 'object') { + const properties = pop(jsonSchema, 'properties') || {}; + + strictSchema['properties'] = Object.fromEntries( + Object.entries(properties).map(([key, propSchema]) => [ + key, + _transformJSONSchema(propSchema as JSONSchema), + ]), + ); + + pop(jsonSchema, 'additionalProperties'); + strictSchema['additionalProperties'] = false; + + const required = pop(jsonSchema, 'required'); + if (required !== undefined) { + strictSchema['required'] = required; + } + } else if (type === 'string') { + const format = pop(jsonSchema, 'format'); + if (format !== undefined && SUPPORTED_STRING_FORMATS.has(format)) { + strictSchema['format'] = format; + } else if (format !== undefined) { + jsonSchema['format'] = format; + } + } else if (type === 'array') { + const items = pop(jsonSchema, 'items'); + if (items !== undefined) { + strictSchema['items'] = _transformJSONSchema(items as JSONSchema); + } + + const minItems = pop(jsonSchema, 'minItems'); + if (minItems !== undefined && (minItems === 0 || minItems === 1)) { + strictSchema['minItems'] = minItems; + } else if (minItems !== undefined) { + jsonSchema['minItems'] = minItems; + } + } + + if (Object.keys(jsonSchema).length > 0) { + const existingDescription = strictSchema['description']; + strictSchema['description'] = + (existingDescription ? existingDescription + '\n\n' : '') + + '{' + + Object.entries(jsonSchema) + .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) + .join(', ') + + '}'; + } + + return strictSchema; +} diff --git a/src/resources/chat/completions/completions.ts b/src/resources/chat/completions/completions.ts index 80e426bdf..62b0df09d 100644 --- a/src/resources/chat/completions/completions.ts +++ b/src/resources/chat/completions/completions.ts @@ -19,6 +19,8 @@ import { ChatCompletionToolRunnerParams } from '../../../lib/ChatCompletionRunne import { ChatCompletionStreamingToolRunnerParams } from '../../../lib/ChatCompletionStreamingRunner'; import { ChatCompletionStream, type ChatCompletionStreamParams } from '../../../lib/ChatCompletionStream'; import { ExtractParsedContentFromParams, parseChatCompletion, validateInputTools } from '../../../lib/parser'; +import { BetaToolRunner, type BetaToolRunnerParams } from '../../../lib/beta/BetaToolRunner'; +import type OpenAI from '../../../index'; export class Completions extends APIResource { messages: MessagesAPI.Messages = new MessagesAPI.Messages(this._client); @@ -192,6 +194,19 @@ export class Completions extends APIResource { return ChatCompletionRunner.runTools(this._client, body as ChatCompletionToolRunnerParams, options); } + toolRunner( + body: BetaToolRunnerParams & { stream?: false }, + options?: BetaToolRunnerRequestOptions, + ): BetaToolRunner; + toolRunner( + body: BetaToolRunnerParams & { stream: true }, + options?: BetaToolRunnerRequestOptions, + ): BetaToolRunner; + toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner; + toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner { + return new BetaToolRunner(this._client as OpenAI, body, options); + } + /** * Creates a chat completion stream */ From 4a719434e61acadd9bc115d1ef0fc9ad3f58609a Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Mon, 1 Dec 2025 17:27:17 -0500 Subject: [PATCH 03/43] more progress on iterative tool calls --- src/helpers/beta/betaZodTool.ts | 0 src/helpers/beta/zod.ts | 70 ++++++++++++++++++++++++++++++--- src/lib/beta/BetaToolRunner.ts | 55 +++++++++++++++++++------- 3 files changed, 105 insertions(+), 20 deletions(-) create mode 100644 src/helpers/beta/betaZodTool.ts diff --git a/src/helpers/beta/betaZodTool.ts b/src/helpers/beta/betaZodTool.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 69ef8f2a4..30e8a2159 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -2,6 +2,8 @@ import { transformJSONSchema } from '../..//lib/transform-json-schema'; import type { infer as zodInfer, ZodType } from 'zod'; import * as z from 'zod'; import { OpenAIError } from '../../core/error'; +import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; +import type { AutoParseableBetaOutputFormat } from '../../lib/beta-parser'; // import { AutoParseableBetaOutputFormat } from '../../lib/beta-parser'; // import { BetaRunnableTool, Promisable } from '../../lib/tools/BetaRunnableTool'; // import { BetaToolResultContentBlockParam } from '../../resources/beta'; @@ -61,12 +63,68 @@ export function betaZodTool(options: { // TypeScript doesn't narrow the type after the runtime check, so we need to assert it const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; + // return { + // type: 'function', // TODO: should this be custom or function? + // name: options.name, + // input_schema: objectSchema, + // description: options.description, + // run: options.run, + // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, + // }; return { - type: 'custom', - name: options.name, - input_schema: objectSchema, - description: options.description, - run: options.run, - parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, + type: 'function', + function: { + name: options.name, + // input_schema: objectSchema, + description: options.description, + // run: options.run, + // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, + parameters: { + type: 'object', + properties: objectSchema.properties, + }, + }, }; } + +// /** +// * Creates a tool using the provided Zod schema that can be passed +// * into the `.toolRunner()` method. The Zod schema will automatically be +// * converted into JSON Schema when passed to the API. The provided function's +// * input arguments will also be validated against the provided schema. +// */ +// export function betaZodTool(options: { +// name: string; +// inputSchema: InputSchema; +// description: string; +// run: (args: zodInfer) => Promisable>; +// }): BetaRunnableTool> { +// const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' }); + +// if (jsonSchema.type !== 'object') { +// throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`); +// } + +// // TypeScript doesn't narrow the type after the runtime check, so we need to assert it +// const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; + +// // return { +// // type: 'function', // TODO: should this be custom or function? +// // name: options.name, +// // input_schema: objectSchema, +// // description: options.description, +// // run: options.run, +// // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, +// // }; +// return { +// type: 'function', +// function: { +// name: options.name, +// // input_schema: objectSchema, +// description: options.description, +// // run: options.run, +// // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, +// parameters: objectSchema.properties ?? {}, // the json schema +// }, +// }; +// } diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 0150c84a7..ae9edfda3 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -72,6 +72,11 @@ export class BetaToolRunner { this.#completion = promiseWithResolvers(); } + get #firstChoiceInCurrentMessage(): ChatCompletionMessageParam | null { + const lastMessage = this.#state.params.messages[this.#state.params.messages.length - 1]; + return lastMessage ?? null; + } + async *[Symbol.asyncIterator](): AsyncIterator< Stream extends true ? ChatCompletionStream // TODO: for now! @@ -112,18 +117,38 @@ export class BetaToolRunner { // this.#message.catch(() => {}); // yield stream as any; } else { - this.#message = this.client.beta.chat.completions.create({ ...params, stream: false }); + console.log('making request with params:', JSON.stringify(params, null, 2)); + this.#message = this.client.beta.chat.completions.create({ + stream: false, + tools: params.tools, + messages: params.messages, + model: params.model, + }); + console.log('Message created:', JSON.stringify(await this.#message, null, 2)); yield this.#message as any; } + if (!this.#message) { + throw new Error('No message created'); // TODO: use better error + } + + // TODO: we should probably hit the user with a callback or somehow offer for them to choice between the choices + const { choices } = await this.#message; + + if (!this.#firstChoiceInCurrentMessage) { + throw new Error('No choices found in message'); // TODO: use better error + } + + const { role: firstChoiceRole, content: firstChoiceContent } = this.#firstChoiceInCurrentMessage; + if (!this.#mutated) { - const { choices } = await this.#message; - const { role, content } = choices[0]!.message; // TODO: ensure there's at least one choice + console.log(choices); // this.#state.params.messages.push({ role, content }); TODO: we want to add all - this.#state.params.messages.push({ role, content }); + this.#state.params.messages.push(this.#firstChoiceInCurrentMessage as ChatCompletionMessageParam); } - const toolMessage = await this.#generateToolResponse(this.#state.params.messages.at(-1)!); + const toolMessage = await this.#generateToolResponse((await this.#message).choices[0]!); + console.log('Tool message:', toolMessage); if (toolMessage) { this.#state.params.messages.push(toolMessage); } @@ -204,15 +229,17 @@ export class BetaToolRunner { if (!message) { return null; } + console.log("Message:", message[0]); // TODO: this cast is probably bad - return this.#generateToolResponse(message as ChatCompletionMessageParam); + return this.#generateToolResponse(message[0]); } - async #generateToolResponse(lastMessage: ChatCompletionMessageParam) { + async #generateToolResponse(lastMessage: ChatCompletion.Choice) { + console.log('Last message:', lastMessage.message); if (this.#toolResponse !== undefined) { return this.#toolResponse; } - this.#toolResponse = generateToolResponse(this.#state.params, lastMessage); + this.#toolResponse = generateToolResponse(this.#state.params, lastMessage.message!); // TODO: maybe undefined return this.#toolResponse; } @@ -313,19 +340,19 @@ export class BetaToolRunner { async function generateToolResponse( params: BetaToolRunnerParams, - lastMessage = params.messages.at(-1), + lastMessageFirstChoice = params.messages.at(-1), ): Promise { // Only process if the last message is from the assistant and has tool use blocks if ( - !lastMessage || - lastMessage.role !== 'assistant' || - !lastMessage.tool_calls || - lastMessage.tool_calls.length === 0 + !lastMessageFirstChoice || + lastMessageFirstChoice.role !== 'assistant' || + !lastMessageFirstChoice.tool_calls || + lastMessageFirstChoice.tool_calls.length === 0 ) { return null; } - const toolUseBlocks = lastMessage.tool_calls.filter((toolCall) => toolCall.type === 'function'); + const toolUseBlocks = lastMessageFirstChoice.tool_calls.filter((toolCall) => toolCall.type === 'function'); if (toolUseBlocks.length === 0) { return null; } From 55d2d775bd3ec5c9ceb3ac5ff698fd094a0b13cb Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Mon, 1 Dec 2025 18:56:12 -0500 Subject: [PATCH 04/43] fix type issues --- src/helpers/beta/zod.ts | 67 +++++-------- src/lib/beta/BetaRunnableTool.ts | 3 +- src/lib/beta/BetaToolRunner.ts | 163 ++++++++++++++++--------------- 3 files changed, 109 insertions(+), 124 deletions(-) diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 30e8a2159..807158175 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -4,6 +4,7 @@ import * as z from 'zod'; import { OpenAIError } from '../../core/error'; import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; import type { AutoParseableBetaOutputFormat } from '../../lib/beta-parser'; +import { FunctionTool } from '../../resources/beta'; // import { AutoParseableBetaOutputFormat } from '../../lib/beta-parser'; // import { BetaRunnableTool, Promisable } from '../../lib/tools/BetaRunnableTool'; // import { BetaToolResultContentBlockParam } from '../../resources/beta'; @@ -52,7 +53,7 @@ export function betaZodTool(options: { name: string; inputSchema: InputSchema; description: string; - run: (args: zodInfer) => Promisable>; + run: (args: zodInfer) => Promisable>; // TODO: I changed this but double check }): BetaRunnableTool> { const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' }); @@ -63,27 +64,18 @@ export function betaZodTool(options: { // TypeScript doesn't narrow the type after the runtime check, so we need to assert it const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; - // return { - // type: 'function', // TODO: should this be custom or function? - // name: options.name, - // input_schema: objectSchema, - // description: options.description, - // run: options.run, - // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, - // }; return { type: 'function', function: { name: options.name, - // input_schema: objectSchema, description: options.description, - // run: options.run, - // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, parameters: { type: 'object', properties: objectSchema.properties, }, }, + run: options.run, + parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, }; } @@ -94,37 +86,26 @@ export function betaZodTool(options: { // * input arguments will also be validated against the provided schema. // */ // export function betaZodTool(options: { -// name: string; -// inputSchema: InputSchema; -// description: string; -// run: (args: zodInfer) => Promisable>; -// }): BetaRunnableTool> { -// const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' }); +// name: string; +// inputSchema: InputSchema; +// description: string; +// run: (args: zodInfer) => Promisable>; +// }): BetaRunnableTool> { +// const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' }); -// if (jsonSchema.type !== 'object') { -// throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`); -// } +// if (jsonSchema.type !== 'object') { +// throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`); +// } -// // TypeScript doesn't narrow the type after the runtime check, so we need to assert it -// const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; +// // TypeScript doesn't narrow the type after the runtime check, so we need to assert it +// const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; -// // return { -// // type: 'function', // TODO: should this be custom or function? -// // name: options.name, -// // input_schema: objectSchema, -// // description: options.description, -// // run: options.run, -// // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, -// // }; -// return { -// type: 'function', -// function: { -// name: options.name, -// // input_schema: objectSchema, -// description: options.description, -// // run: options.run, -// // parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, -// parameters: objectSchema.properties ?? {}, // the json schema -// }, -// }; -// } +// return { +// type: 'custom', +// name: options.name, +// input_schema: objectSchema, +// description: options.description, +// run: options.run, +// parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, +// }; +// } diff --git a/src/lib/beta/BetaRunnableTool.ts b/src/lib/beta/BetaRunnableTool.ts index e05a20bc1..b17cac29c 100644 --- a/src/lib/beta/BetaRunnableTool.ts +++ b/src/lib/beta/BetaRunnableTool.ts @@ -1,3 +1,4 @@ +import { FunctionTool } from '../../resources/beta'; import type { ChatCompletionTool } from '../../resources'; export type Promisable = T | Promise; @@ -5,6 +6,6 @@ export type Promisable = T | Promise; // this type is just an extension of BetaTool with a run and parse method // that will be called by `toolRunner()` helpers export type BetaRunnableTool = ChatCompletionTool & { - run: (args: Input) => Promisable>; + run: (args: Input) => Promisable>; parse: (content: unknown) => Input; }; diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index ae9edfda3..98a50fc46 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -45,7 +45,7 @@ export class BetaToolRunner { /** Promise for the last message received from the assistant */ #message?: Promise | undefined; /** Cached tool response to avoid redundant executions */ - #toolResponse?: Promise | undefined; + #toolResponse?: Promise | undefined; /** Promise resolvers for waiting on completion */ #completion: { promise: Promise; @@ -107,24 +107,21 @@ export class BetaToolRunner { this.#toolResponse = undefined; this.#iterationCount++; - const { max_iterations, ...params } = this.#state.params; + const { ...params } = this.#state.params; if (params.stream) { - throw new Error('TODO'); // TODO - // stream = this.client.beta.chat.completions.stream({ ...params }); - // this.#message = stream.finalMessage(); - // // Make sure that this promise doesn't throw before we get the option to do something about it. - // // Error will be caught when we call await this.#message ultimately - // this.#message.catch(() => {}); - // yield stream as any; + stream = this.client.beta.chat.completions.stream({ ...params, stream: true }); + this.#message = stream.finalMessage(); + // Make sure that this promise doesn't throw before we get the option to do something about it. + // Error will be caught when we call await this.#message ultimately + this.#message?.catch(() => {}); + yield stream as any; } else { - console.log('making request with params:', JSON.stringify(params, null, 2)); this.#message = this.client.beta.chat.completions.create({ stream: false, tools: params.tools, messages: params.messages, model: params.model, }); - console.log('Message created:', JSON.stringify(await this.#message, null, 2)); yield this.#message as any; } @@ -133,27 +130,24 @@ export class BetaToolRunner { } // TODO: we should probably hit the user with a callback or somehow offer for them to choice between the choices - const { choices } = await this.#message; - if (!this.#firstChoiceInCurrentMessage) { throw new Error('No choices found in message'); // TODO: use better error } - const { role: firstChoiceRole, content: firstChoiceContent } = this.#firstChoiceInCurrentMessage; - if (!this.#mutated) { - console.log(choices); // this.#state.params.messages.push({ role, content }); TODO: we want to add all - this.#state.params.messages.push(this.#firstChoiceInCurrentMessage as ChatCompletionMessageParam); + this.#state.params.messages.push(this.#firstChoiceInCurrentMessage); } - const toolMessage = await this.#generateToolResponse((await this.#message).choices[0]!); - console.log('Tool message:', toolMessage); - if (toolMessage) { - this.#state.params.messages.push(toolMessage); + const toolMessages = await this.#generateToolResponse(await this.#message); + if (toolMessages) { + for (const toolMessage of toolMessages) { + this.#state.params.messages.push(toolMessage); + } } - if (!toolMessage && !this.#mutated) { + // TODO: make sure this is correct? + if (!toolMessages && !this.#mutated) { break; } } finally { @@ -229,17 +223,17 @@ export class BetaToolRunner { if (!message) { return null; } - console.log("Message:", message[0]); - // TODO: this cast is probably bad - return this.#generateToolResponse(message[0]); + return this.#generateToolResponse(message); } - async #generateToolResponse(lastMessage: ChatCompletion.Choice) { - console.log('Last message:', lastMessage.message); + async #generateToolResponse(lastMessage: ChatCompletion | ChatCompletionMessageParam) { if (this.#toolResponse !== undefined) { return this.#toolResponse; } - this.#toolResponse = generateToolResponse(this.#state.params, lastMessage.message!); // TODO: maybe undefined + this.#toolResponse = generateToolResponse( + lastMessage, + this.#state.params.tools.filter((tool): tool is BetaRunnableTool => 'run' in tool), + ); return this.#toolResponse; } @@ -339,70 +333,79 @@ export class BetaToolRunner { } async function generateToolResponse( - params: BetaToolRunnerParams, - lastMessageFirstChoice = params.messages.at(-1), -): Promise { + params: ChatCompletion | ChatCompletionMessageParam, + tools: BetaRunnableTool[], +): Promise { + if (!('choices' in params)) { + return null; + } + const { choices } = params; + const lastMessage = choices[0]?.message; + if (!lastMessage) { + return null; + } + // Only process if the last message is from the assistant and has tool use blocks if ( - !lastMessageFirstChoice || - lastMessageFirstChoice.role !== 'assistant' || - !lastMessageFirstChoice.tool_calls || - lastMessageFirstChoice.tool_calls.length === 0 + !lastMessage || + lastMessage.role !== 'assistant' || + !lastMessage.content || + typeof lastMessage.content === 'string' ) { return null; } - const toolUseBlocks = lastMessageFirstChoice.tool_calls.filter((toolCall) => toolCall.type === 'function'); - if (toolUseBlocks.length === 0) { + const { tool_calls: prevToolCalls = [] } = lastMessage; + + if ((lastMessage.tool_calls ?? []).length === 0) { return null; } - const toolResults = await Promise.all( - toolUseBlocks.map(async (toolUse) => { - // TODO: we should be able to infer that toolUseBlocks is FunctionDefinition[] or can cast it (maybe!) - const tool = params.tools.find( - (t) => - ('name' in t && 'function' in t ? t.function.name - : 'name' in t ? t.name - : undefined) === toolUse.function.name, - ); - if (!tool || !('run' in tool)) { - return { - type: 'tool_result' as const, - tool_use_id: toolUse.id, - content: `Error: Tool '${toolUse.function.name}' not found`, - is_error: true, - }; - } - - try { - let input = JSON.parse(toolUse.function.arguments); - if ('parse' in tool && tool.parse) { - input = tool.parse(input); + return ( + await Promise.all( + prevToolCalls.map(async (toolUse) => { + if (toolUse.type !== 'function') return; // TODO: what about other calls? + + const tool = tools.find( + (t) => t.type === 'function' && toolUse.function.name === t.function.name, + ) as BetaRunnableTool; + + if (!tool || !('run' in tool)) { + return { + type: 'tool_result' as const, + tool_call_id: toolUse.id, + content: `Error: Tool '${toolUse.function.name}' not found`, + is_error: true, + }; } - const result = await tool.run(input); - return { - type: 'tool_result' as const, - tool_use_id: toolUse.id, - content: result, - }; - } catch (error) { - return { - type: 'tool_result' as const, - tool_use_id: toolUse.id, - content: `Error: ${error instanceof Error ? error.message : String(error)}`, - is_error: true, - }; - } - }), - ); + try { + let input = toolUse.function.arguments; + input = tool.parse(input); - return { - role: 'tool' as const, - content: JSON.stringify(toolResults), - tool_call_id: toolUseBlocks[0]!.id, - }; + const result = await tool.run(input); + return { + type: 'tool_result' as const, + tool_call_id: toolUse.id, + content: typeof result === 'string' ? result : JSON.stringify(result), + }; + } catch (error) { + return { + type: 'tool_result' as const, + tool_call_id: toolUse.id, + content: `Error: ${error instanceof Error ? error.message : String(error)}`, + is_error: true, + }; + } + }), + ) + ) + .filter((result): result is NonNullable => result != null) + .map((toolResult) => ({ + role: 'tool' as const, + content: toolResult.content, + tool_call_id: toolResult.tool_call_id, + })); } // vendored from typefest just to make things look a bit nicer on hover From 4864dca7baac7f522c506ef92da47c63b474703f Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Mon, 1 Dec 2025 19:53:14 -0500 Subject: [PATCH 05/43] finish port --- examples/tool-calls-beta-zod.ts | 48 ++++++++++++++++++--------------- src/lib/beta/BetaToolRunner.ts | 29 +++++++++++--------- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts index db7fb4337..619b8114b 100644 --- a/examples/tool-calls-beta-zod.ts +++ b/examples/tool-calls-beta-zod.ts @@ -63,11 +63,15 @@ async function main() { const { choices } = message; const firstChoice = choices.at(0)!; - console.log(`${firstChoice.message.content}\n`); // text - // each tool call (could be many) - for (const toolCall of firstChoice.message.tool_calls ?? []) { - if (toolCall.type === 'function') { - console.log(`${toolCall.function.name}(${JSON.stringify(toolCall.function.arguments, null, 2)})\n`); + // When we get a tool call request it's null + if (firstChoice.message.content !== null) { + console.log(`${firstChoice.message.content}\n`); + } else { + // each tool call (could be many) + for (const toolCall of firstChoice.message.tool_calls ?? []) { + if (toolCall.type === 'function') { + console.log(`${toolCall.function.name}(${JSON.stringify(toolCall.function.arguments, null, 2)})\n`); + } } } @@ -75,25 +79,25 @@ async function main() { console.log(); console.log(); - // const defaultResponse = await runner.generateToolResponse(); - // if (defaultResponse && typeof defaultResponse.content !== 'string') { - // console.log(`ā”Œā”€ Response `.padEnd(process.stdout.columns, '─')); - // console.log(); + const defaultResponse = await runner.generateToolResponse(); + if (defaultResponse && Array.isArray(defaultResponse)) { + console.log(`ā”Œā”€ Response `.padEnd(process.stdout.columns, '─')); + console.log(); - // for (const block of defaultResponse.content) { - // if (block.type === 'tool_result') { - // const toolUseBlock = message.content.find((b): b is BetaToolUseBlock => { - // return b.type === 'tool_use' && b.id === block.tool_use_id; - // })!; - // console.log(`${toolUseBlock.name}(): ${block.content}`); - // } - // } + for (const toolResponse of defaultResponse) { + if (toolResponse.role === 'tool') { + const toolCall = firstChoice.message.tool_calls?.find((tc) => tc.id === toolResponse.tool_call_id); + if (toolCall && toolCall.type === 'function') { + console.log(`${toolCall.function.name}(): ${toolResponse.content}`); + } + } + } - // console.log(); - // console.log(`└─`.padEnd(process.stdout.columns, '─')); - // console.log(); - // console.log(); - // } + console.log(); + console.log(`└─`.padEnd(process.stdout.columns, '─')); + console.log(); + console.log(); + } } } diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 98a50fc46..074e16b2d 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -1,3 +1,5 @@ +import type { OpenAI } from '../..'; +import { OpenAIError } from '../../core/error'; import type { ChatCompletion, ChatCompletionCreateParams, @@ -6,8 +8,6 @@ import type { ChatCompletionTool, ChatCompletionToolMessageParam, } from '../../resources/chat/completions'; -import type { OpenAI } from '../..'; -import { OpenAIError } from '../../core/error'; import type { BetaRunnableTool } from './BetaRunnableTool'; // BetaMessage, BetaMessageParam, BetaToolUnion, MessageCreateParams // import { BetaMessageStream } from '../BetaMessageStream'; @@ -72,11 +72,6 @@ export class BetaToolRunner { this.#completion = promiseWithResolvers(); } - get #firstChoiceInCurrentMessage(): ChatCompletionMessageParam | null { - const lastMessage = this.#state.params.messages[this.#state.params.messages.length - 1]; - return lastMessage ?? null; - } - async *[Symbol.asyncIterator](): AsyncIterator< Stream extends true ? ChatCompletionStream // TODO: for now! @@ -130,13 +125,16 @@ export class BetaToolRunner { } // TODO: we should probably hit the user with a callback or somehow offer for them to choice between the choices - if (!this.#firstChoiceInCurrentMessage) { + if (!this.#message) { throw new Error('No choices found in message'); // TODO: use better error } if (!this.#mutated) { - // this.#state.params.messages.push({ role, content }); TODO: we want to add all - this.#state.params.messages.push(this.#firstChoiceInCurrentMessage); + const completion = await this.#message; + // TODO: what if it is empty? + if (completion?.choices && completion.choices.length > 0 && completion.choices[0]!.message) { + this.#state.params.messages.push(completion.choices[0]!.message); + } } const toolMessages = await this.#generateToolResponse(await this.#message); @@ -230,11 +228,12 @@ export class BetaToolRunner { if (this.#toolResponse !== undefined) { return this.#toolResponse; } - this.#toolResponse = generateToolResponse( + const toolsResponse = generateToolResponse( lastMessage, this.#state.params.tools.filter((tool): tool is BetaRunnableTool => 'run' in tool), ); - return this.#toolResponse; + this.#toolResponse = toolsResponse; + return toolsResponse; } /** @@ -349,7 +348,7 @@ async function generateToolResponse( if ( !lastMessage || lastMessage.role !== 'assistant' || - !lastMessage.content || + // !lastMessage.content || TODO: openai doesn't give content at the same time. ensure this is really always true though typeof lastMessage.content === 'string' ) { return null; @@ -381,6 +380,10 @@ async function generateToolResponse( try { let input = toolUse.function.arguments; + // TODO: is this always safe? + if (typeof input === 'string') { + input = JSON.parse(input); + } input = tool.parse(input); const result = await tool.run(input); From 8e55b1ec741e91ef9bec0be1188aec01dfbc2652 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Tue, 2 Dec 2025 09:51:36 -0500 Subject: [PATCH 06/43] add support for options --- examples/tool-calls-beta-zod.ts | 2 ++ src/lib/beta/BetaToolRunner.ts | 27 ++++++++++++++----- src/resources/chat/completions/completions.ts | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts index 619b8114b..185fdcc23 100644 --- a/examples/tool-calls-beta-zod.ts +++ b/examples/tool-calls-beta-zod.ts @@ -99,6 +99,8 @@ async function main() { console.log(); } } + + console.log(JSON.stringify(runner.params, null, 2)); } main(); diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 074e16b2d..efef75e94 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -1,5 +1,7 @@ import type { OpenAI } from '../..'; import { OpenAIError } from '../../core/error'; +import { buildHeaders } from '../../internal/headers'; +import type { RequestOptions } from '../../internal/request-options'; import type { ChatCompletion, ChatCompletionCreateParams, @@ -42,6 +44,7 @@ export class BetaToolRunner { #mutated = false; /** Current state containing the request parameters */ #state: { params: BetaToolRunnerParams }; + #options: BetaToolRunnerRequestOptions; /** Promise for the last message received from the assistant */ #message?: Promise | undefined; /** Cached tool response to avoid redundant executions */ @@ -58,6 +61,7 @@ export class BetaToolRunner { constructor( private client: OpenAI, params: BetaToolRunnerParams, + options?: BetaToolRunnerRequestOptions, ) { this.#state = { params: { @@ -69,6 +73,10 @@ export class BetaToolRunner { }, }; + this.#options = { + ...options, + headers: buildHeaders([{ 'x-stainless-helper': 'BetaToolRunner' }, options?.headers]), + }; this.#completion = promiseWithResolvers(); } @@ -104,19 +112,22 @@ export class BetaToolRunner { const { ...params } = this.#state.params; if (params.stream) { - stream = this.client.beta.chat.completions.stream({ ...params, stream: true }); + stream = this.client.beta.chat.completions.stream({ ...params, stream: true }, this.#options); this.#message = stream.finalMessage(); // Make sure that this promise doesn't throw before we get the option to do something about it. // Error will be caught when we call await this.#message ultimately this.#message?.catch(() => {}); yield stream as any; } else { - this.#message = this.client.beta.chat.completions.create({ - stream: false, - tools: params.tools, - messages: params.messages, - model: params.model, - }); + this.#message = this.client.beta.chat.completions.create( + { + stream: false, + tools: params.tools, + messages: params.messages, + model: params.model, + }, + this.#options, + ); yield this.#message as any; } @@ -428,3 +439,5 @@ export type BetaToolRunnerParams = Simplify< max_iterations?: number; } >; + +export type BetaToolRunnerRequestOptions = Pick; diff --git a/src/resources/chat/completions/completions.ts b/src/resources/chat/completions/completions.ts index 62b0df09d..501025f25 100644 --- a/src/resources/chat/completions/completions.ts +++ b/src/resources/chat/completions/completions.ts @@ -19,7 +19,7 @@ import { ChatCompletionToolRunnerParams } from '../../../lib/ChatCompletionRunne import { ChatCompletionStreamingToolRunnerParams } from '../../../lib/ChatCompletionStreamingRunner'; import { ChatCompletionStream, type ChatCompletionStreamParams } from '../../../lib/ChatCompletionStream'; import { ExtractParsedContentFromParams, parseChatCompletion, validateInputTools } from '../../../lib/parser'; -import { BetaToolRunner, type BetaToolRunnerParams } from '../../../lib/beta/BetaToolRunner'; +import { BetaToolRunner, BetaToolRunnerRequestOptions, type BetaToolRunnerParams } from '../../../lib/beta/BetaToolRunner'; import type OpenAI from '../../../index'; export class Completions extends APIResource { From 95694b6956d23d96208947b6ac314e7498a1908c Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Tue, 2 Dec 2025 10:56:50 -0500 Subject: [PATCH 07/43] update to new async iterable pattern update types start setting up tests get non streaming working begin work on modifying anthropic tests to openai update models --- examples/tool-calls-beta-zod.ts | 7 +- package.json | 12 +- src/lib/beta/BetaToolRunner.ts | 78 +- src/resources/beta/beta.ts | 4 + src/resources/chat/completions/completions.ts | 9 +- tests/lib/tools/ToolRunner.test.ts | 848 ++++++++++++++++++ tests/lib/tools/ToolRunnerE2E.test.ts | 348 +++++++ tests/utils/mock-fetch.ts | 109 ++- yarn.lock | 64 ++ 9 files changed, 1386 insertions(+), 93 deletions(-) create mode 100644 tests/lib/tools/ToolRunner.test.ts create mode 100644 tests/lib/tools/ToolRunnerE2E.test.ts diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts index 185fdcc23..18316b102 100644 --- a/examples/tool-calls-beta-zod.ts +++ b/examples/tool-calls-beta-zod.ts @@ -2,7 +2,6 @@ import OpenAI from 'openai'; import { betaZodTool } from 'openai/helpers/beta/zod'; -// import { BetaToolUseBlock } from 'openai/helpers/beta'; import { z } from 'zod'; const client = new OpenAI(); @@ -12,7 +11,7 @@ async function main() { messages: [ { role: 'user', - content: `I'm planning a trip to San Francisco and I need some information. Can you help me with the weather, current time, and currency exchange rates (from EUR)? Please use parallel tool use`, + content: `I'm planning a trip to San Francisco and I need some information. Can you help me with the weather, current time, and currency exchange rates (from EUR)? Please use parallel tool use.`, }, ], tools: [ @@ -57,6 +56,8 @@ async function main() { console.log(`\nšŸš€ Running tools...\n`); for await (const message of runner) { + if (!message) continue; + console.log(`ā”Œā”€ Message ${message.id} `.padEnd(process.stdout.columns, '─')); console.log(); @@ -99,8 +100,6 @@ async function main() { console.log(); } } - - console.log(JSON.stringify(runner.params, null, 2)); } main(); diff --git a/package.json b/package.json index e34815dd0..e9211895d 100644 --- a/package.json +++ b/package.json @@ -26,18 +26,20 @@ "lint": "./scripts/lint", "fix": "./scripts/format" }, - "dependencies": {}, + "dependencies": { + "nock": "^14.0.10" + }, "devDependencies": { "@arethetypeswrong/cli": "^0.17.0", "@swc/core": "^1.3.102", "@swc/jest": "^0.2.29", "@types/jest": "^29.4.0", - "@types/ws": "^8.5.13", "@types/node": "^20.17.6", + "@types/ws": "^8.5.13", "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", - "deep-object-diff": "^1.1.9", "@typescript-eslint/typescript-estree": "8.31.1", + "deep-object-diff": "^1.1.9", "eslint": "^9.20.1", "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", @@ -53,9 +55,9 @@ "tsconfig-paths": "^4.0.0", "tslib": "^2.8.1", "typescript": "5.8.3", + "typescript-eslint": "8.31.1", "ws": "^8.18.0", - "zod": "^3.25 || ^4.0", - "typescript-eslint": "8.31.1" + "zod": "^3.25 || ^4.0" }, "bin": { "openai": "bin/cli" diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index efef75e94..23d44306d 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -1,10 +1,11 @@ -import type { OpenAI } from '../..'; +import { OpenAI } from '../..'; import { OpenAIError } from '../../core/error'; import { buildHeaders } from '../../internal/headers'; import type { RequestOptions } from '../../internal/request-options'; import type { ChatCompletion, ChatCompletionCreateParams, + ChatCompletionMessage, ChatCompletionMessageParam, ChatCompletionStream, ChatCompletionTool, @@ -45,14 +46,18 @@ export class BetaToolRunner { /** Current state containing the request parameters */ #state: { params: BetaToolRunnerParams }; #options: BetaToolRunnerRequestOptions; - /** Promise for the last message received from the assistant */ - #message?: Promise | undefined; + /** + * Promise for the last message received from the assistant. + * + * This resolves to undefined in non-streaming mode if there are no choices provided. + */ + #message?: Promise | undefined; /** Cached tool response to avoid redundant executions */ #toolResponse?: Promise | undefined; /** Promise resolvers for waiting on completion */ #completion: { - promise: Promise; - resolve: (value: ChatCompletion) => void; + promise: Promise; + resolve: (value: ChatCompletionMessage) => void; reject: (reason?: any) => void; }; /** Number of iterations (API requests) made so far */ @@ -83,8 +88,7 @@ export class BetaToolRunner { async *[Symbol.asyncIterator](): AsyncIterator< Stream extends true ? ChatCompletionStream // TODO: for now! - : Stream extends false ? ChatCompletion - : ChatCompletionCreateParams | ChatCompletionCreateParams + : ChatCompletion | undefined > { if (this.#consumed) { throw new OpenAIError('Cannot iterate over a consumed stream'); @@ -96,7 +100,7 @@ export class BetaToolRunner { try { while (true) { - let stream: any; + let stream: ChatCompletionStream | undefined; try { if ( this.#state.params.max_iterations && @@ -111,16 +115,21 @@ export class BetaToolRunner { this.#iterationCount++; const { ...params } = this.#state.params; + const apiParams = { ...params }; + delete apiParams.max_iterations; // our own param + if (params.stream) { - stream = this.client.beta.chat.completions.stream({ ...params, stream: true }, this.#options); + stream = this.client.beta.chat.completions.stream({ ...apiParams, stream: true }, this.#options); this.#message = stream.finalMessage(); + // Make sure that this promise doesn't throw before we get the option to do something about it. // Error will be caught when we call await this.#message ultimately this.#message?.catch(() => {}); yield stream as any; } else { - this.#message = this.client.beta.chat.completions.create( + const currentCompletion = this.client.beta.chat.completions.create( { + ...apiParams, // spread and explicit so we get better types stream: false, tools: params.tools, messages: params.messages, @@ -128,27 +137,26 @@ export class BetaToolRunner { }, this.#options, ); - yield this.#message as any; - } - if (!this.#message) { - throw new Error('No message created'); // TODO: use better error + yield currentCompletion as any; + + this.#message = currentCompletion.then((resp) => resp.choices.at(0)!.message); } - // TODO: we should probably hit the user with a callback or somehow offer for them to choice between the choices - if (!this.#message) { - throw new Error('No choices found in message'); // TODO: use better error + const prevMessage = await this.#message; + + if (!prevMessage) { + throw new OpenAIError('ToolRunner concluded without a message from the server'); } if (!this.#mutated) { - const completion = await this.#message; // TODO: what if it is empty? - if (completion?.choices && completion.choices.length > 0 && completion.choices[0]!.message) { - this.#state.params.messages.push(completion.choices[0]!.message); + if (prevMessage) { + this.#state.params.messages.push(prevMessage); } } - const toolMessages = await this.#generateToolResponse(await this.#message); + const toolMessages = await this.#generateToolResponse(prevMessage); if (toolMessages) { for (const toolMessage of toolMessages) { this.#state.params.messages.push(toolMessage); @@ -228,15 +236,16 @@ export class BetaToolRunner { * } */ async generateToolResponse() { - const message = (await this.#message) ?? this.params.messages.at(-1); + // The most recent message from the assistant. This prev had this.params.messages.at(-1) but I think that's wrong. + const message = await this.#message; if (!message) { return null; } return this.#generateToolResponse(message); } - async #generateToolResponse(lastMessage: ChatCompletion | ChatCompletionMessageParam) { - if (this.#toolResponse !== undefined) { + async #generateToolResponse(lastMessage: ChatCompletionMessage) { + if (this.#toolResponse) { return this.#toolResponse; } const toolsResponse = generateToolResponse( @@ -263,8 +272,8 @@ export class BetaToolRunner { * const finalMessage = await runner.done(); * console.log('Final response:', finalMessage.content); */ - done(): Promise { - return this.#completion.promise; + done(): Promise { + return this.#completion.promise; // TODO: find a more type safe way to do this } /** @@ -280,7 +289,7 @@ export class BetaToolRunner { * const finalMessage = await runner.runUntilDone(); * console.log('Final response:', finalMessage.content); */ - async runUntilDone(): Promise { + async runUntilDone(): Promise { // If not yet consumed, start consuming and wait for completion if (!this.#consumed) { for await (const _ of this) { @@ -334,8 +343,8 @@ export class BetaToolRunner { * Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone() * This allows using `await runner` instead of `await runner.runUntilDone()` */ - then( - onfulfilled?: ((value: ChatCompletion) => TResult1 | PromiseLike) | undefined | null, + then( // TODO: make sure these types are OK + onfulfilled?: ((value: ChatCompletionMessage) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, ): Promise { return this.runUntilDone().then(onfulfilled, onrejected); @@ -343,18 +352,9 @@ export class BetaToolRunner { } async function generateToolResponse( - params: ChatCompletion | ChatCompletionMessageParam, + lastMessage: ChatCompletionMessage, tools: BetaRunnableTool[], ): Promise { - if (!('choices' in params)) { - return null; - } - const { choices } = params; - const lastMessage = choices[0]?.message; - if (!lastMessage) { - return null; - } - // Only process if the last message is from the assistant and has tool use blocks if ( !lastMessage || diff --git a/src/resources/beta/beta.ts b/src/resources/beta/beta.ts index 4c0528f34..6014b961b 100644 --- a/src/resources/beta/beta.ts +++ b/src/resources/beta/beta.ts @@ -93,6 +93,7 @@ import { ThreadUpdateParams, Threads, } from './threads/threads'; +import { Chat } from './../chat'; export class Beta extends APIResource { realtime: RealtimeAPI.Realtime = new RealtimeAPI.Realtime(this._client); @@ -106,8 +107,11 @@ Beta.Realtime = Realtime; Beta.ChatKit = ChatKit; Beta.Assistants = Assistants; Beta.Threads = Threads; +Beta.Chat = Chat; export declare namespace Beta { + export { Chat }; + export { Realtime as Realtime, type ConversationCreatedEvent as ConversationCreatedEvent, diff --git a/src/resources/chat/completions/completions.ts b/src/resources/chat/completions/completions.ts index 501025f25..7a5207946 100644 --- a/src/resources/chat/completions/completions.ts +++ b/src/resources/chat/completions/completions.ts @@ -19,7 +19,11 @@ import { ChatCompletionToolRunnerParams } from '../../../lib/ChatCompletionRunne import { ChatCompletionStreamingToolRunnerParams } from '../../../lib/ChatCompletionStreamingRunner'; import { ChatCompletionStream, type ChatCompletionStreamParams } from '../../../lib/ChatCompletionStream'; import { ExtractParsedContentFromParams, parseChatCompletion, validateInputTools } from '../../../lib/parser'; -import { BetaToolRunner, BetaToolRunnerRequestOptions, type BetaToolRunnerParams } from '../../../lib/beta/BetaToolRunner'; +import { + BetaToolRunner, + type BetaToolRunnerRequestOptions, + type BetaToolRunnerParams, +} from '../../../lib/beta/BetaToolRunner'; import type OpenAI from '../../../index'; export class Completions extends APIResource { @@ -1998,6 +2002,7 @@ export interface ChatCompletionListParams extends CursorPageParams { } Completions.Messages = Messages; +Completions.BetaToolRunner = BetaToolRunner; export declare namespace Completions { export { @@ -2047,4 +2052,6 @@ export declare namespace Completions { }; export { Messages as Messages, type MessageListParams as MessageListParams }; + + export { BetaToolRunner }; } diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts new file mode 100644 index 000000000..193e1e1b2 --- /dev/null +++ b/tests/lib/tools/ToolRunner.test.ts @@ -0,0 +1,848 @@ +import OpenAI from 'openai'; +// import { BetaMessage, BetaContentBlock, BetaToolResultBlockParam } from 'openai/sdk/resources/beta'; +// import { BetaRunnableTool } from 'openai/sdk/lib/tools/BetaRunnableTool'; +// import { BetaRawMessageStreamEvent } from 'openai/sdk/resources/beta/messages'; +// import { Fetch } from 'openai/sdk/internal/builtin-types'; +import { mockFetch } from '../../utils/mock-fetch'; +import { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; +import { ChatCompletion, ChatCompletionChunk, ChatCompletionCreateParams, ChatCompletionMessage } from 'openai/resources'; +import { Fetch } from 'openai/internal/builtin-types'; +import { ChatCompletionStream } from 'openai/lib/ChatCompletionStream'; + +const weatherTool: BetaRunnableTool<{ location: string }> = { + type: 'function', + function: { + name: 'getWeather', + description: 'Get weather', + parameters: { + type: 'object', + properties: { + location: { type: 'string' }, + }, + }, + }, + run: async ({ location }) => `Sunny in ${location}`, + parse: (input: unknown) => input as { location: string }, +}; + +const calculatorTool: BetaRunnableTool<{ a: number; b: number; operation: string }> = { + type: 'function', + function: { + name: 'calculate', + description: 'Perform calculations', + parameters: { + type: 'object', + properties: { + a: { type: 'number' }, + b: { type: 'number' }, + operation: { type: 'string', enum: ['add', 'multiply'] }, + }, + }, + }, + run: async ({ a, b, operation }) => { + if (operation === 'add') return String(a + b); + if (operation === 'multiply') return String(a * b); + throw new Error(`Unknown operation: ${operation}`); + }, + parse: (input: unknown) => input as { a: number; b: number; operation: string }, +}; + +// Helper functions to create content blocks +function getWeatherToolUse(location: string, id: string = 'tool_1'): BetaContentBlock { + return { type: 'tool_use', id, name: 'getWeather', input: { location } }; +} + +function getWeatherToolResult(location: string, id: string = 'tool_1'): BetaToolResultBlockParam { + return { type: 'tool_result', tool_use_id: id, content: `Sunny in ${location}` }; +} + +function getCalculatorToolUse( + a: number, + b: number, + operation: string, + id: string = 'tool_2', +): BetaContentBlock { + return { + type: 'tool_use', + id, + name: 'calculate', + input: { a, b, operation }, + }; +} + +function getCalculatorToolResult( + a: number, + b: number, + operation: string, + id: string = 'tool_2', +): BetaToolResultBlockParam { + let result: string; + if (operation === 'add') { + result = String(a + b); + } else if (operation === 'multiply') { + result = String(a * b); + } else { + result = `Error: Unknown operation: ${operation}`; + } + return { + type: 'tool_result', + tool_use_id: id, + content: result, + }; +} + +function getTextContent(text?: string): BetaContentBlock { + return { + type: 'text', + text: text || 'Some text content', + citations: null, + }; +} + +function betaMessageToStreamEvents(message: BetaMessage): BetaRawMessageStreamEvent[] { + const events: BetaRawMessageStreamEvent[] = []; + + events.push({ + type: 'message_start', + message: { + id: message.id, + type: message.type, + role: message.role, + model: message.model, + content: [], + stop_reason: null, + stop_sequence: null, + container: null, + context_management: null, + usage: { + cache_creation: null, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, + input_tokens: message.usage.input_tokens, + output_tokens: 0, + server_tool_use: null, + service_tier: null, + }, + }, + }); + + message.content.forEach((block, index) => { + if (block.type === 'text') { + events.push({ + type: 'content_block_start', + index, + content_block: { type: 'text', text: '', citations: null }, + }); + + // Text deltas - always chunked + // Simulate chunked streaming by splitting text + const words = block.text.split(' '); + const chunks = []; + for (let i = 0; i < words.length; i += 2) { + chunks.push(words.slice(i, i + 2).join(' ') + (i + 2 < words.length ? ' ' : '')); + } + chunks.forEach((chunk) => { + if (chunk) { + events.push({ + type: 'content_block_delta', + index, + delta: { type: 'text_delta', text: chunk }, + }); + } + }); + } else if (block.type === 'tool_use') { + events.push({ + type: 'content_block_start', + index, + content_block: { + type: 'tool_use', + id: block.id, + name: block.name, + input: '', + }, + }); + + // Input JSON deltas - always chunked + const jsonStr = JSON.stringify(block.input); + // Simulate chunked JSON streaming + const chunkSize = Math.ceil(jsonStr.length / 3); + for (let i = 0; i < jsonStr.length; i += chunkSize) { + events.push({ + type: 'content_block_delta', + index, + delta: { + type: 'input_json_delta', + partial_json: jsonStr.slice(i, i + chunkSize), + }, + }); + } + } + + events.push({ + type: 'content_block_stop', + index, + }); + }); + + events.push({ + type: 'message_delta', + delta: { + stop_reason: message.stop_reason, + container: message.container, + stop_sequence: message.stop_sequence, + }, + context_management: null, + usage: { + output_tokens: message.usage?.output_tokens || 0, + input_tokens: message.usage?.input_tokens || 0, + cache_creation_input_tokens: null, + cache_read_input_tokens: null, + server_tool_use: null, + }, + }); + + events.push({ + type: 'message_stop', + }); + + return events; +} + +// Overloaded setupTest function for both streaming and non-streaming +interface SetupTestResult { + runner: OpenAI.Beta.Chat.Completions.BetaToolRunner; + fetch: ReturnType['fetch']; + handleRequest: (fetch: Fetch) => void; + handleAssistantMessage: (...content: ChatCompletionMessage[]) => ChatCompletion; + handleAssistantMessageStream: (toolCalls?: ChatCompletionChunk[]) => ChatCompletionStream; +} + +type ToolRunnerParams = Parameters[0]; + +function setupTest(params?: Partial & { stream?: false }): SetupTestResult; +function setupTest(params: Partial & { stream: true }): SetupTestResult; +function setupTest(params: Partial = {}): SetupTestResult { + const { handleRequest, handleStreamEvents, fetch } = mockFetch(); + let messageIdCounter = 0; + + const handleAssistantMessage: SetupTestResult['handleAssistantMessage'] = (...content) => { + const hasToolUse = content.some((block) => (block.tool_calls?.length ?? 0) > 0); + const stop_reason = hasToolUse ? 'tool_use' : 'end_turn'; + + const message: ChatCompletion = { + id: `msg_${messageIdCounter++}`, + object: 'chat.completion', + created: Math.floor(Date.now() / 1000), + model: 'gpt-4', + choices: [ + { + index: 0, + message: { + role: 'assistant', + content: JSON.stringify(content), + refusal: null, + }, + finish_reason: stop_reason === 'tool_use' ? 'tool_calls' : 'stop', + logprobs: null, + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 20, + total_tokens: 30, + }, + }; + handleRequest(async () => { + return new Response(JSON.stringify(message), { + status: 200, + headers: { 'content-type': 'application/json' }, + }); + }); + return message; + }; + + const handleAssistantMessageStream: SetupTestResult['handleAssistantMessageStream'] = ( + ...content + ) => { + const hasToolUse = content.some( + (block) => (block?.at(0)?.choices?.at(0)?.delta?.tool_calls?.length ?? 0) > 0, + ); + const stop_reason = hasToolUse ? 'tool_use' : 'end_turn'; + + const message: ChatCompletion = { + id: `msg_${messageIdCounter++}`, + object: 'chat.completion', + created: Math.floor(Date.now() / 1000), + model: 'gpt-4', + choices: [ + { + index: 0, + message: { + role: 'assistant', + content: JSON.stringify(content), + refusal: null, + }, + finish_reason: stop_reason === 'tool_use' ? 'tool_calls' : 'stop', + logprobs: null, + }, + ], + usage: { + prompt_tokens: 10, + completion_tokens: 20, + total_tokens: 30, + }, + }; + + handleStreamEvents(betaMessageToStreamEvents(message)); + return new ChatCompletionStream(message as ChatCompletionCreateParams); + }; + + const client = new OpenAI({ apiKey: 'test-key', fetch: fetch, maxRetries: 0 }); + + const runnerParams: ToolRunnerParams = { + messages: params.messages || [{ role: 'user', content: 'What is the weather?' }], + model: params.model || 'gpt-4o', + max_tokens: params.max_tokens || 1000, + tools: params.tools || [weatherTool], + ...params, + }; + + const runner = client.beta.chat.completions.toolRunner(runnerParams); + + return { + runner, + fetch, + handleRequest, + handleAssistantMessage, + handleAssistantMessageStream, + }; +} + +async function expectEvent(iterator: AsyncIterator, assertions?: (event: T) => void | Promise) { + const result = await iterator.next(); + expect(result.done).toBe(false); + if (!result.done) { + await assertions?.(result.value); + } +} + +async function expectDone(iterator: AsyncIterator) { + const result = await iterator.next(); + expect(result.done).toBe(true); + expect(result.value).toBeUndefined(); +} + +describe('ToolRunner', () => { + it('throws when consumed multiple times', async () => { + const { runner, handleAssistantMessage } = setupTest(); + + // First consumption - get the iterator explicitly + handleAssistantMessage(getTextContent()); + await runner[Symbol.asyncIterator]().next(); + + // Second attempt to get iterator should throw + handleAssistantMessage(getTextContent()); + expect(async () => await runner[Symbol.asyncIterator]().next()).rejects.toThrow( + 'Cannot iterate over a consumed stream', + ); + }); + + describe('iterator.next()', () => { + it('yields BetaMessage', async () => { + const { runner, handleAssistantMessage } = setupTest(); + + const iterator = runner[Symbol.asyncIterator](); + + handleAssistantMessage(getWeatherToolUse('SF')); + await expectEvent(iterator, (message) => { + expect(message.content).toMatchObject([getWeatherToolUse('SF')]); + }); + + handleAssistantMessage(getTextContent()); + await expectEvent(iterator, (message) => { + expect(message.content).toMatchObject([getTextContent()]); + }); + + await expectDone(iterator); + }); + + it('yields BetaMessageStream when stream=true', async () => { + const { runner, handleAssistantMessageStream } = setupTest({ stream: true }); + + const iterator = runner[Symbol.asyncIterator](); + + // First iteration: assistant requests tool (using helper that generates proper stream events) + handleAssistantMessageStream(getWeatherToolUse('SF')); + await expectEvent(iterator, async (stream) => { + expect(stream.constructor.name).toBe('BetaMessageStream'); + const events = []; + for await (const event of stream) { + events.push(event); + } + // Verify we get the expected number of events (with chunked JSON, we'll get more deltas), but we + // should get at least 6 including + expect(events.length).toBeGreaterThanOrEqual(6); + }); + + // Second iteration: assistant provides final response + handleAssistantMessageStream(getTextContent()); + const result2 = await iterator.next(); + expect(result2.done).toBe(false); + + const stream2 = result2.value; + const events2 = []; + for await (const event of stream2) { + events2.push(event); + } + + // With chunked text, we'll get multiple text_delta events + expect(events2.length).toBeGreaterThanOrEqual(6); + const textDeltas = events2.filter((e) => e.type === 'content_block_delta'); + expect(textDeltas.length).toBeGreaterThanOrEqual(1); + + await expectDone(iterator); + }); + + it('handles multiple tools', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Get weather and calculate 2+3' }], + tools: [weatherTool, calculatorTool], + }); + + const iterator = runner[Symbol.asyncIterator](); + + handleAssistantMessage(getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')); + await expectEvent(iterator, (message) => { + expect(message.content).toHaveLength(2); + expect(message.content).toMatchObject([getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')]); + }); + + // Assistant provides final response + handleAssistantMessage(getTextContent()); + await expectEvent(iterator, (message) => { + expect(message.content).toMatchObject([getTextContent()]); + }); + + // Check that we have both tool results in the messages + // Second message should be assistant with tool uses + // Third message should be user with both tool results + const messages = runner.params.messages; + expect(messages).toHaveLength(3); // user message, assistant with tools, user with results + expect(messages[1]).toMatchObject({ + role: 'assistant', + content: [getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')], + }); + expect(messages[2]).toMatchObject({ + role: 'user', + content: [getWeatherToolResult('NYC'), getCalculatorToolResult(2, 3, 'add', 'tool_2')], + }); + + await expectDone(iterator); + }); + + it('handles missing tool', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Use a tool' }], + tools: [weatherTool], // Only weather tool available + }); + + const iterator = runner[Symbol.asyncIterator](); + + // Assistant requests a tool that doesn't exist + handleAssistantMessage({ + type: 'tool_use', + id: 'tool_1', + name: 'unknownTool', + input: { param: 'value' }, + }); + await expectEvent(iterator, (message) => { + expect(message.content[0]).toMatchObject({ + type: 'tool_use', + name: 'unknownTool', + }); + }); + + // The tool response should contain an error + handleAssistantMessage(getTextContent()); + await expectEvent(iterator, (message) => { + expect(message.content).toMatchObject([getTextContent()]); + }); + + await expectDone(iterator); + }); + + it('handles tool execution errors', async () => { + const errorTool: BetaRunnableTool<{ shouldFail: boolean }> = { + type: 'custom', + name: 'errorTool', + description: 'Tool that can fail', + input_schema: { type: 'object', properties: { shouldFail: { type: 'boolean' } } }, + run: async ({ shouldFail }) => { + if (shouldFail) throw new Error('Tool execution failed'); + return 'Success'; + }, + parse: (input: unknown) => input as { shouldFail: boolean }, + }; + + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Test error handling' }], + tools: [errorTool], + }); + + const iterator = runner[Symbol.asyncIterator](); + + // Assistant requests the error tool with failure flag + handleAssistantMessage({ + type: 'tool_use', + id: 'tool_1', + name: 'errorTool', + input: { shouldFail: true }, + }); + await expectEvent(iterator, (message) => { + expect(message.content[0]).toMatchObject({ + type: 'tool_use', + name: 'errorTool', + }); + }); + + // Assistant handles the error + handleAssistantMessage(getTextContent()); + await expectEvent(iterator, (message) => { + expect(message.content[0]).toMatchObject(getTextContent()); + }); + + // Check that the tool error was properly added to the messages + expect(runner.params.messages).toHaveLength(3); + expect(runner.params.messages[2]).toMatchObject({ + role: 'user', + content: [ + { + type: 'tool_result', + tool_use_id: 'tool_1', + content: expect.stringContaining('Error: Tool execution failed'), + is_error: true, + }, + ], + }); + + await expectDone(iterator); + }); + + it('handles api errors streaming', async () => { + const { runner, handleRequest, handleAssistantMessageStream } = setupTest({ + messages: [{ role: 'user', content: 'Test error handling' }], + tools: [weatherTool], + stream: true, + }); + + handleRequest(async () => { + return new Response(null, { + status: 400, + }); + }); + const iterator1 = runner[Symbol.asyncIterator](); + await expectEvent(iterator1, async (stream) => { + await expect(stream.finalMessage()).rejects.toThrow('400'); + }); + await expect(iterator1.next()).rejects.toThrow('400'); + await expectDone(iterator1); + + // We let you consume the iterator again to continue the conversation when there is an error. + handleAssistantMessageStream(getTextContent()); + const iterator2 = runner[Symbol.asyncIterator](); + await expectEvent(iterator2, (message) => { + expect(message.finalMessage()).resolves.toMatchObject({ content: [getTextContent()] }); + }); + await expectDone(iterator2); + }); + + it('handles api errors', async () => { + const { runner, handleRequest, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Test error handling' }], + tools: [weatherTool], + }); + + handleRequest(async () => { + return new Response(null, { + status: 500, + }); + }); + const iterator1 = runner[Symbol.asyncIterator](); + await expect(iterator1.next()).rejects.toThrow('500'); + await expectDone(iterator1); + + // We let you consume the iterator again to continue the conversation when there is an error. + handleAssistantMessage(getTextContent()); + const iterator2 = runner[Symbol.asyncIterator](); + await expectEvent(iterator2, (message) => { + expect(message.content).toMatchObject([getTextContent()]); + }); + await expectDone(iterator2); + }); + + it('respects max_iterations parameter', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Use tools repeatedly' }], + max_iterations: 2, // Limit to 2 iterations + }); + + const iterator = runner[Symbol.asyncIterator](); + + // First iteration + handleAssistantMessage(getWeatherToolUse('Paris')); + await expectEvent(iterator, (message) => { + expect(message.content).toMatchObject([getWeatherToolUse('Paris')]); + }); + + // Second iteration (should be the last) + handleAssistantMessage(getWeatherToolUse('Berlin', 'tool_2')); + await expectEvent(iterator, (message) => { + expect(message.content).toMatchObject([getWeatherToolUse('Berlin', 'tool_2')]); + }); + + // Should stop here due to max_iterations + await expectDone(iterator); + + // When max_iterations is reached, the iterator completes even if tools were requested. + // The final message would be the last tool_use message from the assistant, + // but no further iterations occur to execute those tools. + const messages = runner.params.messages; + expect(messages).toHaveLength(5); + await expect(runner.runUntilDone()).resolves.toMatchObject({ + role: 'assistant', + content: [getWeatherToolUse('Berlin', 'tool_2')], + }); + }); + }); + + describe('iterator.return()', () => { + it('stops iteration', async () => { + const { runner, handleAssistantMessage } = setupTest(); + + const iterator = runner[Symbol.asyncIterator](); + + handleAssistantMessage(getWeatherToolUse('SF')); + + // Get first message + await expectEvent(iterator); + + // Call return to cleanup + const returnResult = await iterator.return?.(); + expect(returnResult?.done).toBe(true); + expect(returnResult?.value).toBeUndefined(); + + // Further calls should indicate done + await expectDone(iterator); + }); + }); + + describe('.setMessagesParams()', () => { + it('updates parameters for next iteration', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Initial message' }], + max_tokens: 100, + }); + + // Update parameters before iteration + runner.setMessagesParams({ + messages: [{ role: 'user', content: 'Updated message' }], + model: 'gpt-4o', + max_tokens: 200, + tools: [weatherTool], + }); + + const iterator = runner[Symbol.asyncIterator](); + + handleAssistantMessage(getTextContent()); + await expectEvent(iterator, (message) => { + expect(message.content[0]).toMatchObject(getTextContent()); + }); + + // Verify params were updated + expect(runner.params.max_tokens).toBe(200); + expect(runner.params.messages[0]?.content).toBe('Updated message'); + + await expectDone(iterator); + }); + + it('allows you to update append custom tool_use blocks', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Get weather' }], + }); + + const iterator = runner[Symbol.asyncIterator](); + + // First iteration: assistant requests tool + handleAssistantMessage(getWeatherToolUse('Paris')); + await expectEvent(iterator, (message) => { + expect(message.content).toMatchObject([getWeatherToolUse('Paris')]); + }); + + // Verify generateToolResponse returns the tool result for Paris + const toolResponse = await runner.generateToolResponse(); + expect(toolResponse).toMatchObject({ + role: 'user', + content: [getWeatherToolResult('Paris')], + }); + + // Update params to append a custom tool_use block to messages + runner.setMessagesParams((params) => ({ + ...params, + messages: [ + ...params.messages, + { role: 'assistant', content: [getWeatherToolUse('London', 'tool_2')] }, + ], + })); + + // Assistant provides final response incorporating both tool results + handleAssistantMessage(getTextContent()); + await expectEvent(iterator, (message) => { + expect(message.content[0]).toMatchObject(getTextContent()); + }); + + // Verify the messages were properly appended + // The messages array should have: initial user message + custom assistant + custom tool_use + expect(runner.params.messages).toHaveLength(3); + expect(runner.params.messages[1]).toMatchObject({ + role: 'assistant', + content: [getWeatherToolUse('London', 'tool_2')], + }); + // Verify the third message has the London tool_result + // (responded to automatically by the ToolRunner) + expect(runner.params.messages[2]).toMatchObject({ + role: 'user', + content: [getWeatherToolResult('London', 'tool_2')], + }); + await expectDone(iterator); + }); + }); + + describe('.runUntilDone()', () => { + it('consumes iterator if not started', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Test done method' }], + }); + + handleAssistantMessage(getTextContent()); + const finalMessage = await runner.runUntilDone(); + expect(finalMessage.content[0]).toMatchObject(getTextContent()); + }); + }); + + describe('.done()', () => { + it('waits for completion when iterator is consumed', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Test done method' }], + }); + + // Start consuming in background + const consumePromise = (async () => { + for await (const _ of runner) { + // Just consume + } + })(); + + handleAssistantMessage(getTextContent()); + const finalMessage = await runner.done(); + expect(finalMessage.content[0]).toMatchObject(getTextContent()); + + await consumePromise; + }); + }); + + describe('.generateToolResponse()', () => { + it('returns tool response for last message', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Get weather' }], + }); + + const iterator = runner[Symbol.asyncIterator](); + + // First message create call should respond with a tool use. + handleAssistantMessage(getWeatherToolUse('Miami')); + await iterator.next(); + // When we call generateToolResponse, assert that we respond with the tool result. + const toolResponse = await runner.generateToolResponse(); + expect(toolResponse).toMatchObject({ role: 'user', content: [getWeatherToolResult('Miami')] }); + // At this point we should still only have the initial user message + // The assistant message gets added after the yield completes + expect(runner.params.messages.length).toBe(1); + + // Ending the tool loop with an assistant message should work as expected. + handleAssistantMessage(getTextContent()); + await iterator.next(); + await expectDone(iterator); + }); + + it('calls tools at most once', async () => { + let weatherToolCallCount = 0; + const trackingWeatherTool: BetaRunnableTool<{ location: string }> = { + type: 'function', + function: { + name: 'getWeather', + description: 'Get weather', + parameters: { type: 'object', properties: { location: { type: 'string' } } }, + }, + run: async ({ location }) => { + weatherToolCallCount++; + return `Sunny in ${location}`; + }, + parse: (input: unknown) => input as { location: string }, + }; + + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Get weather' }], + tools: [trackingWeatherTool], + }); + + const iterator = runner[Symbol.asyncIterator](); + + // Assistant requests tool + handleAssistantMessage(getWeatherToolUse('Boston')); + await iterator.next(); + + // Tools are executed automatically in the ToolRunner after receiving tool_use blocks + // The generateToolResponse is called internally, which should trigger the tool + // Let's call it manually to verify caching behavior + const response1 = await runner.generateToolResponse(); + expect(weatherToolCallCount).toBe(1); // Tool should be called once + expect(response1).toMatchObject({ + role: 'user', + content: [getWeatherToolResult('Boston')], + }); + const response2 = await runner.generateToolResponse(); + expect(weatherToolCallCount).toBe(1); // Still 1, cached + expect(response2).toMatchObject({ + role: 'user', + content: [getWeatherToolResult('Boston')], + }); + + // Final response should be an assistant response. + handleAssistantMessage(getTextContent()); + await iterator.next(); + + // At this point, the iterator should be completely consumed. + await expectDone(iterator); + + // Since we've never called setMessagesParams(), we should expect the tool to only be called once since it should + // all be cached. Note, that the caching mechanism here should be async-safe. + expect(weatherToolCallCount).toBe(1); + }); + + it('returns null when no tools need execution', async () => { + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Just chat' }], + }); + + const iterator = runner[Symbol.asyncIterator](); + + handleAssistantMessage(getTextContent()); + await iterator.next(); + + // Since the previous block is a text response, we should expect generateToolResponse to return null + const toolResponse = await runner.generateToolResponse(); + expect(toolResponse).toBeNull(); + await expectDone(iterator); + }); + }); +}); diff --git a/tests/lib/tools/ToolRunnerE2E.test.ts b/tests/lib/tools/ToolRunnerE2E.test.ts new file mode 100644 index 000000000..1a256ac24 --- /dev/null +++ b/tests/lib/tools/ToolRunnerE2E.test.ts @@ -0,0 +1,348 @@ +import { OpenAI } from '../../../src'; +import { betaZodTool } from '../../../src/helpers/beta/zod'; +import * as z from 'zod'; +import nock from 'nock'; +import { gunzipSync } from 'zlib'; +import { RequestInfo } from '@openai/sdk/internal/builtin-types'; + +describe('toolRunner integration tests', () => { + let client: OpenAI; + let globalNockDone: (() => void) | undefined; + + beforeAll(async () => { + // Configure nock for recording/playback + nock.back.fixtures = __dirname + '/nockFixtures'; + + const isRecording = process.env['NOCK_RECORD'] === 'true'; + let apiKey = ''; + if (isRecording) { + apiKey = process.env['OPENAI_API_KEY']!; + if (!apiKey) { + throw new Error('you have to have an API key to run new snapshots'); + } + + nock.back.setMode('record'); + + // Configure nock to save readable JSON responses + nock.back.setMode('record'); + nock.recorder.rec({ + dont_print: true, + output_objects: true, + enable_reqheaders_recording: true, + }); + } else { + apiKey = 'test-api-key'; + nock.back.setMode('lockdown'); + } + + // Set up global nock recording/playback with custom transformer + const nockBack = await nock.back('ToolRunner.json', { + // Custom transformer to decompress gzipped responses + afterRecord: (scopes) => { + return scopes.map((scope) => { + const rawHeaders = (scope as any).rawHeaders as Record | undefined; + if ( + scope.response && + Array.isArray(scope.response) && + rawHeaders && + rawHeaders['content-encoding'] === 'gzip' + ) { + try { + // Decompress the gzipped response + const compressed = Buffer.from(scope.response[0], 'hex'); + const decompressed = gunzipSync(compressed); + const jsonResponse = JSON.parse(decompressed.toString()); + + // Replace with readable JSON + scope.response = jsonResponse; + + // Remove gzip header since we decompressed + delete rawHeaders['content-encoding']; + } catch (e) { + // Keep original if decompression fails + console.error('Failed to decompress response:', e); + } + } + return scope; + }); + }, + }); + globalNockDone = nockBack.nockDone; + + // Create a nock-compatible fetch function + const nockCompatibleFetch = async (input: RequestInfo | URL, init?: RequestInit): Promise => { + // Use the global fetch (Node.js 18+ or undici) which nock can intercept + const globalFetch = globalThis.fetch; + if (!globalFetch) { + throw new Error( + 'Global fetch is not available. Ensure you are using Node.js 18+ or have undici available.', + ); + } + return globalFetch(input, init); + }; + + client = new OpenAI({ + apiKey: apiKey, + fetch: nockCompatibleFetch, + }); + }); + + afterAll(() => { + if (globalNockDone) { + globalNockDone(); + } + }); + + // Helper functions for creating common test tools + function createTestTool( + customConfig: Partial<{ + name: string; + inputSchema: z.ZodType; + description: string; + run: (args: any) => any; + }> = {}, + ) { + return betaZodTool({ + name: 'test_tool', + inputSchema: z.object({ value: z.string() }), + description: 'A test tool', + run: () => 'Tool result', + ...customConfig, + }); + } + + function createCounterTool() { + return betaZodTool({ + name: 'test_tool', + inputSchema: z.object({ count: z.number() }), + description: 'A test tool', + run: (args) => `Called with ${args.count}`, + }); + } + + it('should answer tools and run until completion', async () => { + const tool = createTestTool(); + + const runner = client.beta.messages.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + max_iterations: 5, // High limit, should stop before reaching it + messages: [ + { role: 'user', content: 'Use the test_tool with value "test", then provide a final response' }, + ], + tools: [tool], + }); + + const messages = []; + for await (const message of runner) { + messages.push(message); + } + + // Should have exactly 2 messages: tool use + final response + expect(messages).toHaveLength(2); + + // First message should contain one tool use + const firstMessage = messages[0]!; + expect(firstMessage.role).toBe('assistant'); + expect(firstMessage.content).toHaveLength(2); // text + tool_use + + const toolUseBlocks = firstMessage.content.filter((block) => block.type === 'tool_use'); + expect(toolUseBlocks).toHaveLength(1); + expect(toolUseBlocks[0]!.name).toBe('test_tool'); + expect(toolUseBlocks[0]!.input).toEqual({ value: 'test' }); + expect(firstMessage.stop_reason).toBe('tool_use'); + + // Second message should be final response + const secondMessage = messages[1]!; + expect(secondMessage.role).toBe('assistant'); + expect(secondMessage.content).toHaveLength(1); + expect(secondMessage.content[0]!.type).toBe('text'); + expect(secondMessage.stop_reason).toBe('end_turn'); + }); + + describe('max_iterations', () => { + it('should respect max_iterations limit', async () => { + const tool = createCounterTool(); + + const runner = client.beta.messages.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + max_iterations: 2, + messages: [ + { role: 'user', content: 'Use the test_tool with count 1, then use it again with count 2' }, + ], + tools: [tool], + }); + + const messages = []; + for await (const message of runner) { + messages.push(message); + } + + // Should have exactly 2 messages due to max_iterations limit + expect(messages).toHaveLength(2); + + // First message should contain tool uses + const firstMessage = messages[0]!; + expect(firstMessage.role).toBe('assistant'); + expect(firstMessage.content).toHaveLength(3); // text + 2 tool_use blocks + + const toolUseBlocks = firstMessage.content.filter((block) => block.type === 'tool_use'); + expect(toolUseBlocks).toHaveLength(2); + expect(toolUseBlocks[0]!.name).toBe('test_tool'); + expect(toolUseBlocks[0]!.input).toEqual({ count: 1 }); + expect(toolUseBlocks[1]!.name).toBe('test_tool'); + expect(toolUseBlocks[1]!.input).toEqual({ count: 2 }); + + // Second message should be final response + const secondMessage = messages[1]!; + expect(secondMessage.role).toBe('assistant'); + expect(secondMessage.content).toHaveLength(1); + expect(secondMessage.content[0]!.type).toBe('text'); + expect(secondMessage.stop_reason).toBe('end_turn'); + }); + }); + + describe('done()', () => { + it('should consume the iterator and return final message', async () => { + const tool = createTestTool({ inputSchema: z.object({ input: z.string() }) }); + + const runner = client.beta.messages.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + messages: [ + { role: 'user', content: 'Use the test_tool with input "test", then provide a final response' }, + ], + tools: [tool], + }); + + const finalMessage = await runner.runUntilDone(); + + // Final message should be the last text-only response + expect(finalMessage.role).toBe('assistant'); + expect(finalMessage.content).toHaveLength(1); + expect(finalMessage.content[0]).toHaveProperty('type', 'text'); + expect(finalMessage.stop_reason).toBe('end_turn'); + }); + }); + + describe('setMessagesParams()', () => { + it('should update parameters using direct assignment', async () => { + const tool = createTestTool(); + + const runner = client.beta.messages.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + messages: [{ role: 'user', content: 'Hello' }], + tools: [tool], + }); + + // Update parameters + runner.setMessagesParams({ + model: 'gpt-4o', + max_tokens: 500, + messages: [{ role: 'user', content: 'Updated message' }], + tools: [tool], + }); + + const params = runner.params; + expect(params.model).toBe('gpt-4o'); + expect(params.max_tokens).toBe(500); + expect(params.messages).toEqual([{ role: 'user', content: 'Updated message' }]); + }); + }); + + describe('compaction', () => { + it('should compact messages when token threshold is exceeded', async () => { + const tool = { + name: 'submit_analysis', + description: 'Call this LAST with your final analysis.', + input_schema: { + type: 'object' as const, + properties: { + summary: { + type: 'string' as const, + }, + }, + required: ['summary'], + }, + run: async (input: { summary: string }) => { + return 'Analysis submitted'; + }, + }; + + const runner = client.beta.messages.toolRunner({ + model: 'gpt-4o', + max_tokens: 4000, + messages: [ + { + role: 'user', + content: + 'Write a detailed 500-word essay about dogs, cats, and birds. ' + + 'Call the tool `submit_analysis` with the information about all three animals ', + }, + ], + tools: [tool], + compactionControl: { + enabled: true, + contextTokenThreshold: 500, // Low threshold to trigger compaction + }, + max_iterations: 1, + }); + + await runner.runUntilDone(); + expect(runner.params.messages[0]).toMatchInlineSnapshot(` +{ + "content": [ + { + "text": " +## Task Overview +The user requested: +1. Write a detailed 500-word essay about dogs, cats, and birds +2. Call a tool named \`submit_analysis\` with information about all three animals + +Success criteria: +- Essay must be approximately 500 words +- Must cover all three animals (dogs, cats, and birds) +- Must be detailed +- Must call the \`submit_analysis\` tool with the relevant information + +## Current State +**Completed:** Nothing has been completed yet. + +**Status:** The task has just been assigned. No essay has been written, and no tool has been called. + +## Important Discoveries +**Key Issue Identified:** The tool \`submit_analysis\` does not exist in my available tool set. I need to: +1. Either inform the user that this tool is not available, OR +2. Proceed with writing the essay and explain that I cannot call the non-existent tool + +**Technical Constraint:** Without knowing the expected parameters/schema for \`submit_analysis\`, even if it were available, I would need clarification on: +- What format the information should take (structured data, summary points, the full essay text?) +- What specific fields or parameters the tool expects +- Whether separate calls are needed for each animal or one combined call + +## Next Steps +1. **Write the 500-word essay** covering dogs, cats, and birds with detailed information about each animal +2. **Address the tool issue** by either: + - Informing the user that \`submit_analysis\` is not available in my toolkit + - Asking for clarification about what tool they actually meant or how they want the analysis submitted + - Demonstrating what the tool call would look like if it existed +3. **Deliver the essay** in a clear, organized format regardless of tool availability + +## Context to Preserve +- User expects both written content (essay) AND a tool interaction +- The essay should be substantive and detailed, not superficial +- All three animals must receive adequate coverage in the 500-word limit +- No specific style, tone, or audience was specified for the essay (assume general informative style) +- No clarification was provided about whether the essay and tool call should contain the same or different information +", + "type": "text", + }, + ], + "role": "user", +} +`); + }); + }); +}); diff --git a/tests/utils/mock-fetch.ts b/tests/utils/mock-fetch.ts index f8b2184f5..365066ba3 100644 --- a/tests/utils/mock-fetch.ts +++ b/tests/utils/mock-fetch.ts @@ -1,65 +1,86 @@ -import { type Fetch, type RequestInfo, type RequestInit, type Response } from 'openai/internal/builtin-types'; +import { Fetch, RequestInfo, RequestInit } from 'openai/internal/builtin-types'; +import { PassThrough } from 'stream'; -/** - * Creates a mock `fetch` function and a `handleRequest` function for intercepting `fetch` calls. - * - * You call `handleRequest` with a callback function that handles the next `fetch` call. - * It returns a Promise that: - * - waits for the next call to `fetch` - * - calls the callback with the `fetch` arguments - * - resolves `fetch` with the callback output - */ -export function mockFetch(): { fetch: Fetch; handleRequest: (handle: Fetch) => Promise } { - const fetchQueue: ((handler: typeof fetch) => void)[] = []; - const handlerQueue: Promise[] = []; +export function mockFetch(): { + fetch: Fetch; + handleRequest: (handle: Fetch) => void; + handleStreamEvents: (events: any[]) => void; + handleMessageStreamEvents: (iter: AsyncIterable) => void; +} { + const queue: Promise[] = []; + const readResolvers: ((handler: typeof fetch) => void)[] = []; - const enqueueHandler = () => { - handlerQueue.push( - new Promise((resolve) => { - fetchQueue.push((handle: typeof fetch) => { - enqueueHandler(); - resolve(handle); - }); - }), - ); - }; - enqueueHandler(); + let index = 0; async function fetch(req: string | RequestInfo, init?: RequestInit): Promise { - const handler = await handlerQueue.shift(); - if (!handler) throw new Error('expected handler to be defined'); - const signal = init?.signal; - if (!signal) return await handler(req, init); + const idx = index++; + if (!queue[idx]) { + queue.push(new Promise((resolve) => readResolvers.push(resolve))); + } + + const handler = await queue[idx]!; return await Promise.race([ handler(req, init), - new Promise((resolve, reject) => { - if (signal.aborted) { - // @ts-ignore does exist in Node + new Promise((_resolve, reject) => { + if (init?.signal?.aborted) { + // @ts-ignore reject(new DOMException('The user aborted a request.', 'AbortError')); return; } - signal.addEventListener('abort', (e) => { - // @ts-ignore does exist in Node + init?.signal?.addEventListener('abort', (_e) => { + // @ts-ignore reject(new DOMException('The user aborted a request.', 'AbortError')); }); }), ]); } - function handleRequest(handle: typeof fetch): Promise { - return new Promise((resolve, reject) => { - fetchQueue.shift()?.(async (req, init) => { - try { - return await handle(req, init); - } catch (err) { - reject(err); - return err as any; - } finally { - resolve(); + function handleRequest(handler: typeof fetch): void { + if (readResolvers.length) { + const resolver = readResolvers.shift()!; + resolver(handler); + return; + } + queue.push(Promise.resolve(handler)); + } + + function handleStreamEvents(events: any[]) { + handleRequest(async () => { + const stream = new PassThrough(); + (async () => { + for (const event of events) { + stream.write(`event: ${event.type}\n`); + stream.write(`data: ${JSON.stringify(event)}\n\n`); + } + stream.end(`\n`); + })(); + return new Response(stream, { + headers: { + 'Content-Type': 'text/event-stream', + 'Transfer-Encoding': 'chunked', + }, + }); + }); + } + + function handleMessageStreamEvents(iter: AsyncIterable) { + handleRequest(async () => { + const stream = new PassThrough(); + (async () => { + for await (const chunk of iter) { + stream.write(`event: ${chunk.type}\n`); + stream.write(`data: ${JSON.stringify(chunk)}\n\n`); } + stream.end(`\n`); + })(); + return new Response(stream, { + headers: { + 'Content-Type': 'text/event-stream', + 'Transfer-Encoding': 'chunked', + }, }); }); } - return { fetch, handleRequest }; + return { fetch: fetch as any, handleRequest, handleStreamEvents, handleMessageStreamEvents }; } diff --git a/yarn.lock b/yarn.lock index fa13be2ed..0276e1b7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -693,6 +693,18 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@mswjs/interceptors@^0.39.5": + version "0.39.8" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.39.8.tgz#0a2cf4cf26a731214ca4156273121f67dff7ebf8" + integrity sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA== + dependencies: + "@open-draft/deferred-promise" "^2.2.0" + "@open-draft/logger" "^0.3.0" + "@open-draft/until" "^2.0.0" + is-node-process "^1.2.0" + outvariant "^1.4.3" + strict-event-emitter "^0.5.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -714,6 +726,24 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@open-draft/deferred-promise@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" + integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== + +"@open-draft/logger@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" + integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== + dependencies: + is-node-process "^1.2.0" + outvariant "^1.4.0" + +"@open-draft/until@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" + integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== + "@pkgr/core@^0.2.4": version "0.2.4" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" @@ -2020,6 +2050,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: dependencies: is-extglob "^2.1.1" +is-node-process@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" + integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -2491,6 +2526,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + json5@^2.2.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" @@ -2689,6 +2729,15 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +nock@^14.0.10: + version "14.0.10" + resolved "https://registry.yarnpkg.com/nock/-/nock-14.0.10.tgz#d6f4e73e1c6b4b7aa19d852176e68940e15cd19d" + integrity sha512-Q7HjkpyPeLa0ZVZC5qpxBt5EyLczFJ91MEewQiIi9taWuA0KB/MDJlUWtON+7dGouVdADTQsf9RA7TZk6D8VMw== + dependencies: + "@mswjs/interceptors" "^0.39.5" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + node-emoji@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06" @@ -2774,6 +2823,11 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" +outvariant@^1.4.0, outvariant@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" + integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== + p-all@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" @@ -2936,6 +2990,11 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + publint@^0.2.12: version "0.2.12" resolved "https://registry.yarnpkg.com/publint/-/publint-0.2.12.tgz#d25cd6bd243d5bdd640344ecdddb3eeafdcc4059" @@ -3125,6 +3184,11 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +strict-event-emitter@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" + integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" From c4f95d42c5df9f9d23dea4784a732db04937e1a8 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Tue, 2 Dec 2025 15:57:17 -0500 Subject: [PATCH 08/43] fix E2E test --- examples/tool-calls-beta-zod.ts | 1 + tests/lib/tools/ToolRunner.test.ts | 10 +- tests/lib/tools/ToolRunnerE2E.test.ts | 201 +++----- tests/lib/tools/nockFixtures/ToolRunner.json | 474 +++++++++++++++++++ 4 files changed, 544 insertions(+), 142 deletions(-) create mode 100644 tests/lib/tools/nockFixtures/ToolRunner.json diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts index 18316b102..d2e4fb2ae 100644 --- a/examples/tool-calls-beta-zod.ts +++ b/examples/tool-calls-beta-zod.ts @@ -100,6 +100,7 @@ async function main() { console.log(); } } + console.log(JSON.stringify(runner.params.messages, null, 2)); } main(); diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index 193e1e1b2..276033a4d 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -5,7 +5,7 @@ import OpenAI from 'openai'; // import { Fetch } from 'openai/sdk/internal/builtin-types'; import { mockFetch } from '../../utils/mock-fetch'; import { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; -import { ChatCompletion, ChatCompletionChunk, ChatCompletionCreateParams, ChatCompletionMessage } from 'openai/resources'; +import { ChatCompletion, ChatCompletionChunk, ChatCompletionMessage, ChatCompletionTool, ChatCompletionToolMessageParam } from 'openai/resources'; import { Fetch } from 'openai/internal/builtin-types'; import { ChatCompletionStream } from 'openai/lib/ChatCompletionStream'; @@ -48,12 +48,12 @@ const calculatorTool: BetaRunnableTool<{ a: number; b: number; operation: string }; // Helper functions to create content blocks -function getWeatherToolUse(location: string, id: string = 'tool_1'): BetaContentBlock { +function getWeatherToolUse(location: string, id: string = 'tool_1'): ChatCompletionFunctionTool { return { type: 'tool_use', id, name: 'getWeather', input: { location } }; } -function getWeatherToolResult(location: string, id: string = 'tool_1'): BetaToolResultBlockParam { - return { type: 'tool_result', tool_use_id: id, content: `Sunny in ${location}` }; +function getWeatherToolResult(location: string, id: string = 'tool_1'): ChatCompletionToolMessageParam { + return { role: 'tool', tool_use_id: id, content: `Sunny in ${location}` }; } function getCalculatorToolUse( @@ -294,7 +294,7 @@ function setupTest(params: Partial = {}): SetupTestResult { let client: OpenAI; @@ -78,7 +78,7 @@ describe('toolRunner integration tests', () => { 'Global fetch is not available. Ensure you are using Node.js 18+ or have undici available.', ); } - return globalFetch(input, init); + return await globalFetch(input, init); }; client = new OpenAI({ @@ -123,12 +123,16 @@ describe('toolRunner integration tests', () => { it('should answer tools and run until completion', async () => { const tool = createTestTool(); - const runner = client.beta.messages.toolRunner({ + const runner = client.beta.chat.completions.toolRunner({ model: 'gpt-4o', max_tokens: 1000, max_iterations: 5, // High limit, should stop before reaching it messages: [ - { role: 'user', content: 'Use the test_tool with value "test", then provide a final response' }, + { + role: 'user', + content: + 'Use the test_tool with value "test", then provide a final response that includes the word \'foo\'.', + }, ], tools: [tool], }); @@ -142,34 +146,34 @@ describe('toolRunner integration tests', () => { expect(messages).toHaveLength(2); // First message should contain one tool use - const firstMessage = messages[0]!; - expect(firstMessage.role).toBe('assistant'); - expect(firstMessage.content).toHaveLength(2); // text + tool_use - - const toolUseBlocks = firstMessage.content.filter((block) => block.type === 'tool_use'); - expect(toolUseBlocks).toHaveLength(1); - expect(toolUseBlocks[0]!.name).toBe('test_tool'); - expect(toolUseBlocks[0]!.input).toEqual({ value: 'test' }); - expect(firstMessage.stop_reason).toBe('tool_use'); - - // Second message should be final response - const secondMessage = messages[1]!; - expect(secondMessage.role).toBe('assistant'); - expect(secondMessage.content).toHaveLength(1); - expect(secondMessage.content[0]!.type).toBe('text'); - expect(secondMessage.stop_reason).toBe('end_turn'); + const firstMessage = messages[0]!.choices[0]!; + expect(firstMessage.message.role).toBe('assistant'); + expect(firstMessage.message.content).toBeNull(); // openai only responds with tool use and null content + expect(firstMessage.message.tool_calls).toHaveLength(1); // the tool call should be present + expect(firstMessage.finish_reason).toBe('tool_calls'); + + // Second message should be final response with text + expect(messages[1]!.choices).toHaveLength(1); + const secondMessage = messages[1]!.choices[0]!; + expect(secondMessage.message.role).toBe('assistant'); + expect(secondMessage.message.content).toContain('foo'); + expect(secondMessage.finish_reason).toBe('stop'); }); describe('max_iterations', () => { it('should respect max_iterations limit', async () => { const tool = createCounterTool(); - const runner = client.beta.messages.toolRunner({ + const runner = client.beta.chat.completions.toolRunner({ model: 'gpt-4o', max_tokens: 1000, max_iterations: 2, messages: [ - { role: 'user', content: 'Use the test_tool with count 1, then use it again with count 2' }, + { + role: 'user', + content: + "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message", + }, ], tools: [tool], }); @@ -183,23 +187,37 @@ describe('toolRunner integration tests', () => { expect(messages).toHaveLength(2); // First message should contain tool uses - const firstMessage = messages[0]!; - expect(firstMessage.role).toBe('assistant'); - expect(firstMessage.content).toHaveLength(3); // text + 2 tool_use blocks + const firstMessage = messages[0]!.choices[0]!; + expect(firstMessage.message.role).toBe('assistant'); + expect(firstMessage.message.content).toBeNull(); + expect(firstMessage.message.tool_calls).toHaveLength(2); - const toolUseBlocks = firstMessage.content.filter((block) => block.type === 'tool_use'); + const { tool_calls: toolUseBlocks } = firstMessage.message; + expect(toolUseBlocks).toBeDefined(); expect(toolUseBlocks).toHaveLength(2); - expect(toolUseBlocks[0]!.name).toBe('test_tool'); - expect(toolUseBlocks[0]!.input).toEqual({ count: 1 }); - expect(toolUseBlocks[1]!.name).toBe('test_tool'); - expect(toolUseBlocks[1]!.input).toEqual({ count: 2 }); - - // Second message should be final response - const secondMessage = messages[1]!; - expect(secondMessage.role).toBe('assistant'); - expect(secondMessage.content).toHaveLength(1); - expect(secondMessage.content[0]!.type).toBe('text'); - expect(secondMessage.stop_reason).toBe('end_turn'); + + if (toolUseBlocks && toolUseBlocks[0] && toolUseBlocks[0].type === 'function') { + expect(toolUseBlocks[0].function).toBeDefined(); + expect(toolUseBlocks[0].function.name).toBe('test_tool'); + expect(JSON.parse(toolUseBlocks[0].function.arguments)).toEqual({ count: 1 }); + } else { + // Doing it with an if else to get nice type inference + throw new Error('Expected tool call at index 0 to be a function'); + } + + if (toolUseBlocks && toolUseBlocks[1] && toolUseBlocks[1].type === 'function') { + expect(toolUseBlocks[1].function).toBeDefined(); + expect(toolUseBlocks[1].function.name).toBe('test_tool'); + expect(JSON.parse(toolUseBlocks[1].function.arguments)).toEqual({ count: 2 }); + } else { + throw new Error('Expected tool call at index 1 to be a function'); + } + + // Second message should be final response (not a tool call) + const secondMessage = messages[1]!.choices[0]!; + expect(secondMessage.message.role).toBe('assistant'); + expect(secondMessage.message.content).toContain('231'); + expect(secondMessage.finish_reason).toBe('stop'); }); }); @@ -207,11 +225,15 @@ describe('toolRunner integration tests', () => { it('should consume the iterator and return final message', async () => { const tool = createTestTool({ inputSchema: z.object({ input: z.string() }) }); - const runner = client.beta.messages.toolRunner({ + const runner = client.beta.chat.completions.toolRunner({ model: 'gpt-4o', max_tokens: 1000, messages: [ - { role: 'user', content: 'Use the test_tool with input "test", then provide a final response' }, + { + role: 'user', + content: + 'Use the test_tool with input "test", then provide a final response with the word \'231\'', + }, ], tools: [tool], }); @@ -220,9 +242,8 @@ describe('toolRunner integration tests', () => { // Final message should be the last text-only response expect(finalMessage.role).toBe('assistant'); - expect(finalMessage.content).toHaveLength(1); - expect(finalMessage.content[0]).toHaveProperty('type', 'text'); - expect(finalMessage.stop_reason).toBe('end_turn'); + expect(finalMessage.tool_calls).toBeUndefined(); + expect(finalMessage.content).toContain('231'); }); }); @@ -230,7 +251,7 @@ describe('toolRunner integration tests', () => { it('should update parameters using direct assignment', async () => { const tool = createTestTool(); - const runner = client.beta.messages.toolRunner({ + const runner = client.beta.chat.completions.toolRunner({ model: 'gpt-4o', max_tokens: 1000, messages: [{ role: 'user', content: 'Hello' }], @@ -251,98 +272,4 @@ describe('toolRunner integration tests', () => { expect(params.messages).toEqual([{ role: 'user', content: 'Updated message' }]); }); }); - - describe('compaction', () => { - it('should compact messages when token threshold is exceeded', async () => { - const tool = { - name: 'submit_analysis', - description: 'Call this LAST with your final analysis.', - input_schema: { - type: 'object' as const, - properties: { - summary: { - type: 'string' as const, - }, - }, - required: ['summary'], - }, - run: async (input: { summary: string }) => { - return 'Analysis submitted'; - }, - }; - - const runner = client.beta.messages.toolRunner({ - model: 'gpt-4o', - max_tokens: 4000, - messages: [ - { - role: 'user', - content: - 'Write a detailed 500-word essay about dogs, cats, and birds. ' + - 'Call the tool `submit_analysis` with the information about all three animals ', - }, - ], - tools: [tool], - compactionControl: { - enabled: true, - contextTokenThreshold: 500, // Low threshold to trigger compaction - }, - max_iterations: 1, - }); - - await runner.runUntilDone(); - expect(runner.params.messages[0]).toMatchInlineSnapshot(` -{ - "content": [ - { - "text": " -## Task Overview -The user requested: -1. Write a detailed 500-word essay about dogs, cats, and birds -2. Call a tool named \`submit_analysis\` with information about all three animals - -Success criteria: -- Essay must be approximately 500 words -- Must cover all three animals (dogs, cats, and birds) -- Must be detailed -- Must call the \`submit_analysis\` tool with the relevant information - -## Current State -**Completed:** Nothing has been completed yet. - -**Status:** The task has just been assigned. No essay has been written, and no tool has been called. - -## Important Discoveries -**Key Issue Identified:** The tool \`submit_analysis\` does not exist in my available tool set. I need to: -1. Either inform the user that this tool is not available, OR -2. Proceed with writing the essay and explain that I cannot call the non-existent tool - -**Technical Constraint:** Without knowing the expected parameters/schema for \`submit_analysis\`, even if it were available, I would need clarification on: -- What format the information should take (structured data, summary points, the full essay text?) -- What specific fields or parameters the tool expects -- Whether separate calls are needed for each animal or one combined call - -## Next Steps -1. **Write the 500-word essay** covering dogs, cats, and birds with detailed information about each animal -2. **Address the tool issue** by either: - - Informing the user that \`submit_analysis\` is not available in my toolkit - - Asking for clarification about what tool they actually meant or how they want the analysis submitted - - Demonstrating what the tool call would look like if it existed -3. **Deliver the essay** in a clear, organized format regardless of tool availability - -## Context to Preserve -- User expects both written content (essay) AND a tool interaction -- The essay should be substantive and detailed, not superficial -- All three animals must receive adequate coverage in the 500-word limit -- No specific style, tone, or audience was specified for the essay (assume general informative style) -- No clarification was provided about whether the essay and tool call should contain the same or different information -", - "type": "text", - }, - ], - "role": "user", -} -`); - }); - }); }); diff --git a/tests/lib/tools/nockFixtures/ToolRunner.json b/tests/lib/tools/nockFixtures/ToolRunner.json new file mode 100644 index 000000000..5a15ef5be --- /dev/null +++ b/tests/lib/tools/nockFixtures/ToolRunner.json @@ -0,0 +1,474 @@ +[ + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "value": { + "type": "string" + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b3404201c07ce392f9674370bc94efe64815e55fdd411cb03dfd840a050cf2b7479e5956869eb28b0f43db8dc3fbf2db4986eb607beb7b91f131b3c45c3b28453ca361b41a33e11419d36a7a73dab77eb50ec0144f2676e5e65ec2e7e8e1fddefc93c885f77d12593efbb9b2970a565d898cfd8d0104531f4010924c1fd7c06a2ae29ba600a82baa18d306f8755c72a259ba65356308e4d6de3fc37777f06febea0712f81c05ce4514c406e8b9a329b3a88fb11864b86f5617918038634885adab74df99faaab40f61f28fd3c26ce97adc9dfb5f1f4ba3d1efdc22d859718d30262c122e18b13514847128621b8a00ee45d525796590b2d1a66105dacbf08b1ff0b4feff917c77af13a2daf37f887062fd8999b42d4c4d6dad6b990bc949561d5944eabddac0235295d8ca8c39bd9c2569cd6c7b45bb5fa79d551b2efb54093e6528c0be19ea8608a84204fd7a2376c11ffc39e6f94e12d4f26ca36ccee304696c7db93f6f6e480abe322dc159382d0a2e743a89ba824bfa8a92275b3759cf587d4c57e03504711a7bad0a237f860b941fa7ead48334cc7f60cdfb4d105" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbb91b9d442f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:45 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "332", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=lpPj9JFyqlPPHP_HkoosAVe0qXpd8Sv7nn2TbPz.7XU-1764709005788-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "648", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999974", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_f2c619799e6a49df915d7151b34af812" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." + }, + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_kXFjbYa63Zq8QTBFFenco0Si", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"value\":\"test\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + { + "role": "tool", + "content": "Tool result", + "tool_call_id": "call_kXFjbYa63Zq8QTBFFenco0Si" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "value": { + "type": "string" + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b6603081c056eacc77324e1504f6156da56b599addfbcc35ad5bc0970c1ac411494fab6820e4b57ffffaf768687561aa1c063f9dbf2da16d174bd53bb15771248c3b284b3989b591b471afd303be6a72f0c558a603bff961cc541ee54e36a48c3a2d77fce75db6b3e5df25b6bb47cf5ec76b030cc534bc3271224a68c7d4774d7b15ccdd734bb1603e5d162216eb245b2adce64cdeb46a7564e20996fa8ea2f019367fe4493186a2a4304ab946f10376336ff0683d4cc794ed3a75d6607f6942046dffb945d0e91f22b6df15dcc0edb8a17819c4831a17e03984507410e00605bc5e4e865f73f9db70e54880bc5571511d61bf9514b3c0ee310d216d86e5ddf576209e2424771e314e18a479e935c609f00aa745b1c2c643fd27429247e6c70dd03884129d8dc24410a04e4f8778fead03ee4023c599d8a16016d47c4dd2acebc81abe78dda328b9dfe155936f9adca2e08dc8f80249d88df7c23ac94a3bf73c11dcf8fa3d4cbfc080e" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbb966db942f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:46 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "453", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=dIQGF8J5UWhZ4SvG6kU7vUjxKahEtpjMKX7lCEQJmWA-1764709006362-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "470", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999969", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_94e15302a82b469cb4d179718e715ba0" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "count": { + "type": "number" + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b1205601c0776d356336ef452185b7fa2989c27747bf5885a1bdb4a7d19d3c8f1223edcdf538745e18f7b779fe3d0c2147abb318777f19e1e25169695684a89628b6ec24c3f62d29e6ccf6e287400c8e3d7ecb448483ddc84eba0eb95ac3ed07c39163efadc6ea7eac1daacd6f09083ca36f6f311182f5a5e03ac2c0932a3328cf4260bf1d4ef170d29e46493d64946210ffc96ee773e5d076e80bc76b20c01121f7280aa4899e90190f53318abfd95a4c6c731581f418cae6996e7fa6d58a090f217509905c754284ec38b255ffaa3fd32bb74b3bdc9c33c585678d5e44d233084f9318ec4d42233966e108db4a75d2dc94858fade2ae0e02df097ff88cfbf8dc3f7f16f81df6a617c5905523c49fc8fa46d4b2be2c7fc7af19ab3757d132dffd5d0779a5101635d47e76b5ba41e2bc9fda2caad9a37dce01ac691c099a8a54896b00d97b5e51aafb8b5d2a2c1716ca00624e5b456338d61dd8240dd3f86b8c7b21c212f82bd3d1ef250a357c4a198ec241ab9c6316cf87473e615cefedf1c66fed7303ad84570ee132553e96427541e59945d2f23da3036a15b0130471096c7bc08ee9d888652aadbb705ba0aabbabcc02b16f401" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbb99e86742f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:47 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "1458", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=qi330.nZqpWAjkxgfpHpx2xbkc2UcZcgIVqzaBpJOJc-1764709007921-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "1470", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999973", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_5d9e0413b7b942aeb8212d70c86dc374" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" + }, + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"count\": 1}" + } + }, + { + "id": "call_3SAikZPh6kJlgz6ASqbj3I3Q", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"count\": 2}" + } + } + ], + "refusal": null, + "annotations": [] + }, + { + "role": "tool", + "content": "Called with 1", + "tool_call_id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3" + }, + { + "role": "tool", + "content": "Called with 2", + "tool_call_id": "call_3SAikZPh6kJlgz6ASqbj3I3Q" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "count": { + "type": "number" + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b4903201c056eacc77324e150cf1165c4dc52dd7d9e6945bdd9c404681085abbeada0c3d275eae63d4771420b30965fedc18145d15ab6388134cdb4053d8b9111aef1af2f044207811d988d9d1609350f6fe17d71de620ce65e789b66c7eba3f5db6cbd6f8e021602262a84ad1f904030a89c6f84536451613596558f5847b428fb4543893955a619c5aad7967ca4f50ff22707ee8b09bbe198b0e493d48a10e1d1358a0d92a0c67d87c1a9d1684b5ec9815aa9c1bdb56b6d3ffdc0d37881a3a7fff48f35139cf92d582b665873fb7bf7afebab24f78b2ab76a6a0ba569e979040c645a086b1ec47b6d5b333d149b222d1a3dffa535c209e20a516823280b9c361dd0954ab2b4f5a4687bd544dabbceb91d029cf26d18d1bd5fa1b1ec89f137c3cc3fb7614a95d87ad36c1bddc1a4df5e244b7534f3a7a550d79bd0ad1034170c27c562eb5f6b836b106155bd42771d59141cf49226c101" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbba3983a42f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:48 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "570", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=BUCKnZnfZHCGps3vl2nGYAx9wF.sgTuV.Mr9F4AhkTk-1764709008586-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "585", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999963", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_7d1925a5797891a7b7bb58f383b71d92" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "input": { + "type": "string" + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b3404201c07ce392f9674370bc94efe64819ed37e73c4b9103ead4353a8e715babcf24ab4b4751458fafefce5ee385b6831f4e66f0f3c6f73372636788a866509a7946d3522d8a53e11418db6ae8ef6ecee5d3b64bf0122f9b3971f796cc75edb9b57642741a771627d3fdf4ffaf96fa0652b63696343535445cf0f48600919e73310754dd10553108c9d6cc4b6fd8b325609d9349db282716e6abbe4bfbd7b19f8c782e6bd04027353663101b92d4a426fe920ee4718ae19d687e55e0c19d2206a99b1f364ffa57115cafe0365b3774739471d63775ad6ddbc7614d9eeb83b13d34262e1aae10b123190998917c6e0a23a92774959187addb39a30a3e8a2bd22e8ce159edef315c776f1baccae37e40f0d565a889b3cd4a4dedadeb990bce485bf28099fa976b30ad4a474b1fc0e6f668b58715a1ed36ed1e6f85146c9be97024d6c9918e7c14ba24229e2814abaea7f608bf8eff57ca30c6fbd65fc6ca3ecf6626c79b03d511fcf0eb8da0e7e87c1b420b4e8fde019c62f291f6a2acbb8397792f58794d99f04a08e12ce75a1455ff0a17243f4fd1ad1c710cd8facc8c6135d" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbba86c8b42f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:49 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "985", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=oJb88Mguy0KPy3QsA56AonUav8eXZp4Vndi.eTdWPoE-1764709009776-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "1002", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999976", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_dc3243bab67944a1b586d7a40f600776" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" + }, + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_tMdC4ZpC8UYPyDuyj43iCkU9", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"input\":\"test\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + { + "role": "tool", + "content": "Tool result", + "tool_call_id": "call_tMdC4ZpC8UYPyDuyj43iCkU9" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "input": { + "type": "string" + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b2303201c076eac66e4a0959313a8725ea1a6ea277ab6b4add4974f1cc86fd1930ef7d4615198ba79cf6dce3496ff6f4f0ea4eb7c2d4b274918269c8a6e88495279076f8f56a54090e46f4937b6f4503daa57b2cc7be44517af39c5f2f1be5f57a10e8b27603488f2858d0f4810cf909e53044acf99260f84086afc8e282b17e34acd40cd34a5c29f9bae97ec1f641fecf84723dc308e05d929a148c079256d1edad801b96fe0e3126854ef949683f41b7f5cd462b56e640d81e0d7b22e71f6228fdaa118e7215eae36b33b139504e8a0460154c2cc38c0eb0d83db58e5ddb8a272a37b86be2d1631dc386ea90c6b44f332ca6bdfcf427137f93252682b3da74d2e56e6e631f1c5bb5f67e8ed45e437abbe189bc764fdb7d01d3621b7ce94c22512a4b04c4c52f22aae553603c16de0e3a2195818600db62e74d6773e62e6cb20d346fb313400" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbbaf5bd142f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:50 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "422", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=cePexYFkijPVWrWqH3vLF2RIg.1dy1YjD_.Dp8_n7Nk-1764709010314-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "435", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999971", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_4e047e9ec0344280be4d034850f217b5" + }, + "responseIsBinary": false + } +] \ No newline at end of file From f2834e972d63f83c95574d8c594804b17bdb6b32 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Tue, 2 Dec 2025 17:01:30 -0500 Subject: [PATCH 09/43] fix more tests --- tests/lib/tools/ToolRunner.test.ts | 117 ++++++++++++++++++----------- 1 file changed, 73 insertions(+), 44 deletions(-) diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index 276033a4d..9db86e951 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -5,7 +5,15 @@ import OpenAI from 'openai'; // import { Fetch } from 'openai/sdk/internal/builtin-types'; import { mockFetch } from '../../utils/mock-fetch'; import { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; -import { ChatCompletion, ChatCompletionChunk, ChatCompletionMessage, ChatCompletionTool, ChatCompletionToolMessageParam } from 'openai/resources'; +import { + ChatCompletion, + ChatCompletionChunk, + ChatCompletionFunctionTool, + ChatCompletionMessage, + ChatCompletionMessageToolCall, + ChatCompletionTool, + ChatCompletionToolMessageParam, +} from 'openai/resources'; import { Fetch } from 'openai/internal/builtin-types'; import { ChatCompletionStream } from 'openai/lib/ChatCompletionStream'; @@ -48,12 +56,19 @@ const calculatorTool: BetaRunnableTool<{ a: number; b: number; operation: string }; // Helper functions to create content blocks -function getWeatherToolUse(location: string, id: string = 'tool_1'): ChatCompletionFunctionTool { - return { type: 'tool_use', id, name: 'getWeather', input: { location } }; +function getWeatherToolUse(location: string, id: string = 'tool_1'): ChatCompletionMessageToolCall { + return { + id: id, + type: 'function', + function: { + name: 'getWeather', + arguments: JSON.stringify({ location }), + }, + }; } function getWeatherToolResult(location: string, id: string = 'tool_1'): ChatCompletionToolMessageParam { - return { role: 'tool', tool_use_id: id, content: `Sunny in ${location}` }; + return { role: 'tool', tool_call_id: id, content: `Sunny in ${location}` }; } function getCalculatorToolUse( @@ -61,12 +76,14 @@ function getCalculatorToolUse( b: number, operation: string, id: string = 'tool_2', -): BetaContentBlock { +): ChatCompletionMessageToolCall { return { - type: 'tool_use', - id, - name: 'calculate', - input: { a, b, operation }, + id: id, + type: 'function', + function: { + name: 'calculate', + arguments: JSON.stringify({ a, b, operation }), + }, }; } @@ -75,7 +92,7 @@ function getCalculatorToolResult( b: number, operation: string, id: string = 'tool_2', -): BetaToolResultBlockParam { +): ChatCompletionToolMessageParam { let result: string; if (operation === 'add') { result = String(a + b); @@ -85,13 +102,13 @@ function getCalculatorToolResult( result = `Error: Unknown operation: ${operation}`; } return { - type: 'tool_result', - tool_use_id: id, + role: 'tool', + tool_call_id: id, content: result, }; } -function getTextContent(text?: string): BetaContentBlock { +function getTextContent(text?: string): ChatCompletionMessage { return { type: 'text', text: text || 'Some text content', @@ -213,21 +230,34 @@ interface SetupTestResult { runner: OpenAI.Beta.Chat.Completions.BetaToolRunner; fetch: ReturnType['fetch']; handleRequest: (fetch: Fetch) => void; - handleAssistantMessage: (...content: ChatCompletionMessage[]) => ChatCompletion; + handleAssistantMessage: (firstChoice: ToolCallsOrMessage) => ChatCompletion; handleAssistantMessageStream: (toolCalls?: ChatCompletionChunk[]) => ChatCompletionStream; } type ToolRunnerParams = Parameters[0]; +type ToolCallsOrMessage = ChatCompletionMessageToolCall[] | ChatCompletionMessage; + function setupTest(params?: Partial & { stream?: false }): SetupTestResult; function setupTest(params: Partial & { stream: true }): SetupTestResult; function setupTest(params: Partial = {}): SetupTestResult { const { handleRequest, handleStreamEvents, fetch } = mockFetch(); let messageIdCounter = 0; - const handleAssistantMessage: SetupTestResult['handleAssistantMessage'] = (...content) => { - const hasToolUse = content.some((block) => (block.tool_calls?.length ?? 0) > 0); - const stop_reason = hasToolUse ? 'tool_use' : 'end_turn'; + const handleAssistantMessage: SetupTestResult['handleAssistantMessage'] = ( + messageContentOrToolCalls, + ) => { + const isToolCalls = Array.isArray(messageContentOrToolCalls); + + const messageContent = + isToolCalls ? + { + role: 'assistant' as const, + tool_calls: messageContentOrToolCalls, + refusal: null, + content: null, + } + : (messageContentOrToolCalls as ChatCompletionMessage); // TODO: check that this is right const message: ChatCompletion = { id: `msg_${messageIdCounter++}`, @@ -237,12 +267,8 @@ function setupTest(params: Partial = {}): SetupTestResult = {}): SetupTestResult { return new Response(JSON.stringify(message), { status: 200, @@ -261,11 +288,9 @@ function setupTest(params: Partial = {}): SetupTestResult['handleAssistantMessageStream'] = ( - ...content - ) => { - const hasToolUse = content.some( - (block) => (block?.at(0)?.choices?.at(0)?.delta?.tool_calls?.length ?? 0) > 0, + const handleAssistantMessageStream: SetupTestResult['handleAssistantMessageStream'] = (...chunks) => { + const hasToolUse = chunks.some( + (chunk) => (chunk?.at(0)?.choices?.at(0)?.delta?.tool_calls?.length ?? 0) > 0, ); const stop_reason = hasToolUse ? 'tool_use' : 'end_turn'; @@ -279,7 +304,7 @@ function setupTest(params: Partial = {}): SetupTestResult { }); describe('iterator.next()', () => { - it('yields BetaMessage', async () => { + it('yields CompletionMessage', async () => { const { runner, handleAssistantMessage } = setupTest(); const iterator = runner[Symbol.asyncIterator](); - handleAssistantMessage(getWeatherToolUse('SF')); + handleAssistantMessage([getWeatherToolUse('SF')]); + await expectEvent(iterator, (message) => { - expect(message.content).toMatchObject([getWeatherToolUse('SF')]); + expect(message?.choices[0]?.message.tool_calls).toMatchObject([getWeatherToolUse('SF')]); }); handleAssistantMessage(getTextContent()); + await expectEvent(iterator, (message) => { - expect(message.content).toMatchObject([getTextContent()]); + expect(message?.choices[0]?.message).toMatchObject(getTextContent()); }); await expectDone(iterator); @@ -411,32 +438,34 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); - handleAssistantMessage(getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')); + handleAssistantMessage([getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')]); await expectEvent(iterator, (message) => { - expect(message.content).toHaveLength(2); - expect(message.content).toMatchObject([getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')]); + expect(message?.choices).toHaveLength(1); + expect(message?.choices[0]?.message.tool_calls).toHaveLength(2); + expect(message?.choices[0]?.message.tool_calls).toMatchObject([ + getWeatherToolUse('NYC'), + getCalculatorToolUse(2, 3, 'add'), + ]); }); // Assistant provides final response handleAssistantMessage(getTextContent()); await expectEvent(iterator, (message) => { - expect(message.content).toMatchObject([getTextContent()]); + expect(message?.choices).toHaveLength(1); + expect(message?.choices[0]?.message).toMatchObject(getTextContent()); }); // Check that we have both tool results in the messages // Second message should be assistant with tool uses // Third message should be user with both tool results const messages = runner.params.messages; - expect(messages).toHaveLength(3); // user message, assistant with tools, user with results + expect(messages).toHaveLength(4); // user message, assistant with tools, tool result 1, tool result 2, assistant final expect(messages[1]).toMatchObject({ role: 'assistant', - content: [getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')], + tool_calls: [getWeatherToolUse('NYC'), getCalculatorToolUse(2, 3, 'add')], }); - expect(messages[2]).toMatchObject({ - role: 'user', - content: [getWeatherToolResult('NYC'), getCalculatorToolResult(2, 3, 'add', 'tool_2')], - }); - + expect(messages[2]).toMatchObject(getWeatherToolResult('NYC')); + expect(messages[3]).toMatchObject(getCalculatorToolResult(2, 3, 'add', 'tool_2')); await expectDone(iterator); }); From 34421a06d2fe164cd64c2d3479d4b80f2a347688 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Tue, 2 Dec 2025 18:43:57 -0500 Subject: [PATCH 10/43] fix more tests --- src/lib/beta/BetaToolRunner.ts | 13 +- .../embeddings-base64-response.json | 13 +- .../embeddings-float-response.json | 50 +- tests/lib/tools/ToolRunner.test.ts | 141 +-- tests/lib/tools/nockFixtures/ToolRunner.json | 918 +++++++++--------- 5 files changed, 615 insertions(+), 520 deletions(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 23d44306d..9178e3e1a 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -52,6 +52,12 @@ export class BetaToolRunner { * This resolves to undefined in non-streaming mode if there are no choices provided. */ #message?: Promise | undefined; + /** + * Resolves to the last (entire) chat completion received from the assistant. + * We want to return an attribute of ourself so that the promise keeps running + * after the yield, and we can access it later. + */ + #chatCompletion?: Promise; /** Cached tool response to avoid redundant executions */ #toolResponse?: Promise | undefined; /** Promise resolvers for waiting on completion */ @@ -127,7 +133,7 @@ export class BetaToolRunner { this.#message?.catch(() => {}); yield stream as any; } else { - const currentCompletion = this.client.beta.chat.completions.create( + this.#chatCompletion = this.client.beta.chat.completions.create( { ...apiParams, // spread and explicit so we get better types stream: false, @@ -138,9 +144,10 @@ export class BetaToolRunner { this.#options, ); - yield currentCompletion as any; + this.#message = this.#chatCompletion.then((resp) => resp.choices.at(0)!.message); + await this.#message; // TODO: we would like to not need to await it - this.#message = currentCompletion.then((resp) => resp.choices.at(0)!.message); + yield this.#chatCompletion as any; } const prevMessage = await this.#message; diff --git a/tests/api-resources/embeddings-base64-response.json b/tests/api-resources/embeddings-base64-response.json index 9b0f7629c..9e552d5a1 100644 --- a/tests/api-resources/embeddings-base64-response.json +++ b/tests/api-resources/embeddings-base64-response.json @@ -1 +1,12 @@ -{"object":"list","data":[{"object":"embedding","index":0,"embedding":"A1fLvaC4Bb0QB7w8yEvrPOm9Xj2r0yA8EW4sPRq75j3Fbiq81/chPumAGb0afqG8R6AFvpzsQT35SPO7Hi39PEMAir1lf0A92McfvRoVlLxQv9o9tHqIvQYlrL0fwlK8sufPPYz2gjzH5Ho93GebvN+eCTxjRjW8PJRKvXMtFD4+n3C9ByMPO39Gkjs1Jm49A1fLPdNXpjv8RLm92McfveKpLz01VNO9SUIevhAHvD0flG09+9srvW5j7Txp8dY8LW4Ju08bJb1GdL29g+aNPWlLBD1p8dY8LkCkvfPLtjxcBj4+1/ehPebv/bz/Ifo8SqkOvREFHzyAr588HbUPPbFS+r00gri825WAPQlcGj1qHZ+8o8EOPo880Tn5dli9zRUSPc2APD0b5RG9mhxEvTyUSj3FQMU95u/9vE20tD3wwBC94NmxvXSUhL3Ofh8904WLPRbeJb2Paja8BClmvhwgOj2e6Ic9em0LPdj1BD3lSau7dJQEPJi107yB6kc97sTKO6lAaD2YDwE9YDuPPSFVC735dtg9SK1IOysJNrwtQkE8BmJxPb2ZXT0hVYs9g+YNvLfuuz2nyhe9z7nHN5UVWDxea5E77F1avTIbyL256oG9ft+hPVWJAbwNoug82TCtvUrm072wgN86JPWGO3TRyTwOY4a8xJwPvkx5DL1f1B68RwkTvja7Q72BrQI9Pfs6PTdfeb3RxG09jJxVvfl22D3eCbQ9FbR6vTPtYrn0mzS+kqGkPDxXhbwyG8i98M9wveayuL1EpL88lNqvve3yL70RQmQ7VcZGPaPBjr1wyEA9fKaWOskMibwNomi8J9Rku9EeGz016Si8O1mivQ38lb0EgxO88P1VvcilmLuNA0a9lj8DvHCceD3lSSs9uFWsve6HBT6XEZ68ShS5PFJSE70dTIK86OvDvSNgsbzS8DU8bPz8PAuVpTxKQIE9/NmOPBhFFj7LsL67PJRKvIxu8LwSqVS8D8yTPSOOlj1g0gG8A+69vYz2AjxPhLK80fLSPbrL/LztWz09LAcZvqfKF73B/JO8lnzIvCk5OLxwMU69dmQCvQtp3bs6hwe9WZKKume4S7x3CLg9zK4hPLsjDT16P6a7MbTXPRp+IT0dtQ89GayGvcngwD2F8bO70R4bu8tFlDxcBr67xAWdvdnWfzzQTIC9zn6fPYSKwz3alx28h8GxPW74wj3eNxk+xUBFvIpjyj0WdRi9AkoIPXhvqLugx+U8F0ezvUlCHjx3NAC9uvlhPEOmXD36oAM9D56uvddgrz2giiC9GhWUvHrWGLv0yRk8fOPbvMc+KLs7//S8v5UjPJUV2D0KLjW6YKa5PDciNDuJznQ9USZLPQ=="}],"model":"text-embedding-3-large","usage":{"prompt_tokens":1,"total_tokens":1}} \ No newline at end of file +{ + "object": "list", + "data": [ + { + "object": "embedding", + "index": 0, + "embedding": "A1fLvaC4Bb0QB7w8yEvrPOm9Xj2r0yA8EW4sPRq75j3Fbiq81/chPumAGb0afqG8R6AFvpzsQT35SPO7Hi39PEMAir1lf0A92McfvRoVlLxQv9o9tHqIvQYlrL0fwlK8sufPPYz2gjzH5Ho93GebvN+eCTxjRjW8PJRKvXMtFD4+n3C9ByMPO39Gkjs1Jm49A1fLPdNXpjv8RLm92McfveKpLz01VNO9SUIevhAHvD0flG09+9srvW5j7Txp8dY8LW4Ju08bJb1GdL29g+aNPWlLBD1p8dY8LkCkvfPLtjxcBj4+1/ehPebv/bz/Ifo8SqkOvREFHzyAr588HbUPPbFS+r00gri825WAPQlcGj1qHZ+8o8EOPo880Tn5dli9zRUSPc2APD0b5RG9mhxEvTyUSj3FQMU95u/9vE20tD3wwBC94NmxvXSUhL3Ofh8904WLPRbeJb2Paja8BClmvhwgOj2e6Ic9em0LPdj1BD3lSau7dJQEPJi107yB6kc97sTKO6lAaD2YDwE9YDuPPSFVC735dtg9SK1IOysJNrwtQkE8BmJxPb2ZXT0hVYs9g+YNvLfuuz2nyhe9z7nHN5UVWDxea5E77F1avTIbyL256oG9ft+hPVWJAbwNoug82TCtvUrm072wgN86JPWGO3TRyTwOY4a8xJwPvkx5DL1f1B68RwkTvja7Q72BrQI9Pfs6PTdfeb3RxG09jJxVvfl22D3eCbQ9FbR6vTPtYrn0mzS+kqGkPDxXhbwyG8i98M9wveayuL1EpL88lNqvve3yL70RQmQ7VcZGPaPBjr1wyEA9fKaWOskMibwNomi8J9Rku9EeGz016Si8O1mivQ38lb0EgxO88P1VvcilmLuNA0a9lj8DvHCceD3lSSs9uFWsve6HBT6XEZ68ShS5PFJSE70dTIK86OvDvSNgsbzS8DU8bPz8PAuVpTxKQIE9/NmOPBhFFj7LsL67PJRKvIxu8LwSqVS8D8yTPSOOlj1g0gG8A+69vYz2AjxPhLK80fLSPbrL/LztWz09LAcZvqfKF73B/JO8lnzIvCk5OLxwMU69dmQCvQtp3bs6hwe9WZKKume4S7x3CLg9zK4hPLsjDT16P6a7MbTXPRp+IT0dtQ89GayGvcngwD2F8bO70R4bu8tFlDxcBr67xAWdvdnWfzzQTIC9zn6fPYSKwz3alx28h8GxPW74wj3eNxk+xUBFvIpjyj0WdRi9AkoIPXhvqLugx+U8F0ezvUlCHjx3NAC9uvlhPEOmXD36oAM9D56uvddgrz2giiC9GhWUvHrWGLv0yRk8fOPbvMc+KLs7//S8v5UjPJUV2D0KLjW6YKa5PDciNDuJznQ9USZLPQ==" + } + ], + "model": "text-embedding-3-large", + "usage": { "prompt_tokens": 1, "total_tokens": 1 } +} diff --git a/tests/api-resources/embeddings-float-response.json b/tests/api-resources/embeddings-float-response.json index 9b5b788e2..bf179a36e 100644 --- a/tests/api-resources/embeddings-float-response.json +++ b/tests/api-resources/embeddings-float-response.json @@ -1 +1,49 @@ -{"object":"list","data":[{"object":"embedding","index":0,"embedding":[-0.099287055,-0.032646775,0.022952586,0.028722659,0.05438033,0.009816091,0.042097155,0.112661555,-0.010402386,0.158172,-0.037476454,-0.01971345,-0.13049422,0.04734479,-0.0074244705,0.030905303,-0.06738331,0.046996493,-0.039008945,-0.018076468,0.10681021,-0.06664029,-0.08405499,-0.012863665,0.10151614,0.015986703,0.061253335,-0.018970422,0.008399694,-0.011064145,-0.049457774,0.14470463,-0.058745615,0.0021840946,0.00446397,0.058141906,0.099287055,0.0050763874,-0.09046361,-0.039008945,0.042886622,-0.103187956,-0.15454973,0.091810346,0.058002587,-0.041957837,0.028978076,0.02623816,-0.002097021,-0.040309247,-0.09250693,0.06928732,0.03229848,0.02623816,-0.08020054,0.022314047,0.18557113,0.079086,-0.030998182,0.030533789,-0.034829415,0.009705798,0.019492865,0.035084832,-0.122228034,-0.022523023,0.06278583,0.037685428,-0.019423205,0.13941054,0.00039908706,-0.052847836,0.035665322,0.04602127,-0.035618883,-0.04787884,0.049457774,0.096314944,-0.030998182,0.08823452,-0.03534025,-0.086841345,-0.06473628,0.03893929,0.06812634,-0.040495,-0.011133804,-0.22476584,0.045440778,0.06636165,0.03403995,0.032461017,-0.005227315,0.008092035,-0.025843427,0.048807625,0.0061880266,0.05670229,0.031509012,0.06993747,-0.034016732,0.10569567,0.0030620862,-0.011110584,0.011795563,0.058931373,0.054101694,0.068033464,-0.008660915,0.091763906,-0.0370585,0.000023809172,0.013188739,0.004437848,-0.053312227,-0.09770812,-0.06343598,0.07903956,-0.007906278,0.028397584,-0.084565826,-0.103466585,0.0017051902,0.0041185785,0.024636008,-0.016404655,-0.14024645,-0.034295365,-0.009694188,-0.14359008,-0.04778596,0.031903747,0.045649756,-0.06088182,0.058049027,-0.052151248,0.10569567,0.087909445,-0.061206896,-0.00021641403,-0.17637616,0.020096574,-0.016276948,-0.09770812,-0.058792055,-0.09018497,0.023393758,-0.08586612,-0.04295628,0.0034829418,0.048528988,-0.06970527,0.047066152,0.0011493708,-0.01672973,-0.014198792,-0.0034916492,0.037871186,-0.010309507,-0.079271756,-0.073234655,-0.0090034045,-0.052244127,-0.0046584345,-0.04834323,-0.008010766,0.060696065,0.04181852,-0.08414787,0.13040134,-0.019295497,0.022592682,-0.03596718,-0.015905434,-0.0956648,-0.021652287,0.011104779,0.030882083,0.02021267,0.0631109,0.017437927,0.14674795,-0.005819415,-0.012364443,-0.029349588,-0.012979763,0.072166555,0.07351329,-0.007923692,-0.09273913,0.007993352,-0.021791605,0.1030022,-0.030858863,0.046230245,-0.14944142,-0.0370585,-0.018064858,-0.02447347,-0.011244097,-0.050340116,-0.03183409,-0.006756907,-0.033087946,-0.001057218,-0.012434102,0.089859895,0.009868335,0.034457903,-0.005073485,0.10532416,0.0394269,0.035084832,-0.06575794,0.09417874,-0.005491438,-0.002366949,0.018099686,-0.005799098,-0.07667115,0.0156151885,-0.06264651,0.07787858,0.09547904,-0.009618724,0.086794905,0.095200405,0.14962718,-0.012039368,0.09882267,-0.037221037,0.033273704,-0.0051402412,0.02804929,-0.08753794,0.009659358,-0.031300034,0.01379245,0.053869497,0.03213594,-0.08526241,0.085633926,-0.039194703,-0.018076468,-0.0023321197,0.009386528,-0.026841871,-0.0025672184,-0.02990686,0.009984433,0.105509914,-0.00069114624,0.022662342,0.0027486214,0.05976728,0.04959709]}],"model":"text-embedding-3-large","usage":{"prompt_tokens":1,"total_tokens":1}} \ No newline at end of file +{ + "object": "list", + "data": [ + { + "object": "embedding", + "index": 0, + "embedding": [ + -0.099287055, -0.032646775, 0.022952586, 0.028722659, 0.05438033, 0.009816091, 0.042097155, + 0.112661555, -0.010402386, 0.158172, -0.037476454, -0.01971345, -0.13049422, 0.04734479, + -0.0074244705, 0.030905303, -0.06738331, 0.046996493, -0.039008945, -0.018076468, 0.10681021, + -0.06664029, -0.08405499, -0.012863665, 0.10151614, 0.015986703, 0.061253335, -0.018970422, + 0.008399694, -0.011064145, -0.049457774, 0.14470463, -0.058745615, 0.0021840946, 0.00446397, + 0.058141906, 0.099287055, 0.0050763874, -0.09046361, -0.039008945, 0.042886622, -0.103187956, + -0.15454973, 0.091810346, 0.058002587, -0.041957837, 0.028978076, 0.02623816, -0.002097021, + -0.040309247, -0.09250693, 0.06928732, 0.03229848, 0.02623816, -0.08020054, 0.022314047, 0.18557113, + 0.079086, -0.030998182, 0.030533789, -0.034829415, 0.009705798, 0.019492865, 0.035084832, + -0.122228034, -0.022523023, 0.06278583, 0.037685428, -0.019423205, 0.13941054, 0.00039908706, + -0.052847836, 0.035665322, 0.04602127, -0.035618883, -0.04787884, 0.049457774, 0.096314944, + -0.030998182, 0.08823452, -0.03534025, -0.086841345, -0.06473628, 0.03893929, 0.06812634, -0.040495, + -0.011133804, -0.22476584, 0.045440778, 0.06636165, 0.03403995, 0.032461017, -0.005227315, + 0.008092035, -0.025843427, 0.048807625, 0.0061880266, 0.05670229, 0.031509012, 0.06993747, + -0.034016732, 0.10569567, 0.0030620862, -0.011110584, 0.011795563, 0.058931373, 0.054101694, + 0.068033464, -0.008660915, 0.091763906, -0.0370585, 0.000023809172, 0.013188739, 0.004437848, + -0.053312227, -0.09770812, -0.06343598, 0.07903956, -0.007906278, 0.028397584, -0.084565826, + -0.103466585, 0.0017051902, 0.0041185785, 0.024636008, -0.016404655, -0.14024645, -0.034295365, + -0.009694188, -0.14359008, -0.04778596, 0.031903747, 0.045649756, -0.06088182, 0.058049027, + -0.052151248, 0.10569567, 0.087909445, -0.061206896, -0.00021641403, -0.17637616, 0.020096574, + -0.016276948, -0.09770812, -0.058792055, -0.09018497, 0.023393758, -0.08586612, -0.04295628, + 0.0034829418, 0.048528988, -0.06970527, 0.047066152, 0.0011493708, -0.01672973, -0.014198792, + -0.0034916492, 0.037871186, -0.010309507, -0.079271756, -0.073234655, -0.0090034045, -0.052244127, + -0.0046584345, -0.04834323, -0.008010766, 0.060696065, 0.04181852, -0.08414787, 0.13040134, + -0.019295497, 0.022592682, -0.03596718, -0.015905434, -0.0956648, -0.021652287, 0.011104779, + 0.030882083, 0.02021267, 0.0631109, 0.017437927, 0.14674795, -0.005819415, -0.012364443, -0.029349588, + -0.012979763, 0.072166555, 0.07351329, -0.007923692, -0.09273913, 0.007993352, -0.021791605, + 0.1030022, -0.030858863, 0.046230245, -0.14944142, -0.0370585, -0.018064858, -0.02447347, + -0.011244097, -0.050340116, -0.03183409, -0.006756907, -0.033087946, -0.001057218, -0.012434102, + 0.089859895, 0.009868335, 0.034457903, -0.005073485, 0.10532416, 0.0394269, 0.035084832, -0.06575794, + 0.09417874, -0.005491438, -0.002366949, 0.018099686, -0.005799098, -0.07667115, 0.0156151885, + -0.06264651, 0.07787858, 0.09547904, -0.009618724, 0.086794905, 0.095200405, 0.14962718, -0.012039368, + 0.09882267, -0.037221037, 0.033273704, -0.0051402412, 0.02804929, -0.08753794, 0.009659358, + -0.031300034, 0.01379245, 0.053869497, 0.03213594, -0.08526241, 0.085633926, -0.039194703, + -0.018076468, -0.0023321197, 0.009386528, -0.026841871, -0.0025672184, -0.02990686, 0.009984433, + 0.105509914, -0.00069114624, 0.022662342, 0.0027486214, 0.05976728, 0.04959709 + ] + } + ], + "model": "text-embedding-3-large", + "usage": { "prompt_tokens": 1, "total_tokens": 1 } +} diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index 9db86e951..e0b09609e 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -8,10 +8,8 @@ import { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; import { ChatCompletion, ChatCompletionChunk, - ChatCompletionFunctionTool, ChatCompletionMessage, ChatCompletionMessageToolCall, - ChatCompletionTool, ChatCompletionToolMessageParam, } from 'openai/resources'; import { Fetch } from 'openai/internal/builtin-types'; @@ -110,9 +108,9 @@ function getCalculatorToolResult( function getTextContent(text?: string): ChatCompletionMessage { return { - type: 'text', - text: text || 'Some text content', - citations: null, + role: 'assistant', + content: text || 'Some text content', + refusal: null, }; } @@ -478,23 +476,35 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); // Assistant requests a tool that doesn't exist - handleAssistantMessage({ - type: 'tool_use', - id: 'tool_1', - name: 'unknownTool', - input: { param: 'value' }, - }); + handleAssistantMessage([ + { + type: 'function', + id: 'tool', + function: { + name: 'unknownTool', + arguments: JSON.stringify({ param: 'value' }), + }, + }, + ]); + await expectEvent(iterator, (message) => { - expect(message.content[0]).toMatchObject({ - type: 'tool_use', - name: 'unknownTool', - }); + expect(message?.choices?.[0]?.message.tool_calls).toMatchObject([ + { + type: 'function', + id: 'tool', + function: { + name: 'unknownTool', + arguments: JSON.stringify({ param: 'value' }), + }, + }, + ]); }); // The tool response should contain an error handleAssistantMessage(getTextContent()); await expectEvent(iterator, (message) => { - expect(message.content).toMatchObject([getTextContent()]); + // TODO: this seems sketchy + expect(message?.choices?.[0]?.message).toMatchObject(getTextContent()); }); await expectDone(iterator); @@ -502,10 +512,12 @@ describe('ToolRunner', () => { it('handles tool execution errors', async () => { const errorTool: BetaRunnableTool<{ shouldFail: boolean }> = { - type: 'custom', - name: 'errorTool', - description: 'Tool that can fail', - input_schema: { type: 'object', properties: { shouldFail: { type: 'boolean' } } }, + type: 'function', + function: { + name: 'errorTool', + description: 'Tool that can fail', + parameters: { type: 'object', properties: { shouldFail: { type: 'boolean' } } }, + }, run: async ({ shouldFail }) => { if (shouldFail) throw new Error('Tool execution failed'); return 'Success'; @@ -521,37 +533,38 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); // Assistant requests the error tool with failure flag - handleAssistantMessage({ - type: 'tool_use', - id: 'tool_1', - name: 'errorTool', - input: { shouldFail: true }, - }); + handleAssistantMessage([ + { + id: 'tool_1', + type: 'function', + function: { + name: 'errorTool', + arguments: JSON.stringify({ shouldFail: true }), + }, + }, + ]); + await expectEvent(iterator, (message) => { - expect(message.content[0]).toMatchObject({ - type: 'tool_use', - name: 'errorTool', + expect(message?.choices[0]?.message.tool_calls?.[0]).toMatchObject({ + type: 'function', + function: { + name: 'errorTool', + }, }); }); // Assistant handles the error handleAssistantMessage(getTextContent()); await expectEvent(iterator, (message) => { - expect(message.content[0]).toMatchObject(getTextContent()); + expect(message?.choices[0]?.message).toMatchObject(getTextContent()); }); // Check that the tool error was properly added to the messages expect(runner.params.messages).toHaveLength(3); expect(runner.params.messages[2]).toMatchObject({ - role: 'user', - content: [ - { - type: 'tool_result', - tool_use_id: 'tool_1', - content: expect.stringContaining('Error: Tool execution failed'), - is_error: true, - }, - ], + role: 'tool', + tool_call_id: 'tool_1', + content: expect.stringContaining('Error: Tool execution failed'), }); await expectDone(iterator); @@ -604,7 +617,7 @@ describe('ToolRunner', () => { handleAssistantMessage(getTextContent()); const iterator2 = runner[Symbol.asyncIterator](); await expectEvent(iterator2, (message) => { - expect(message.content).toMatchObject([getTextContent()]); + expect(message?.choices?.[0]?.message).toMatchObject(getTextContent()); }); await expectDone(iterator2); }); @@ -618,15 +631,17 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); // First iteration - handleAssistantMessage(getWeatherToolUse('Paris')); + handleAssistantMessage([getWeatherToolUse('Paris')]); await expectEvent(iterator, (message) => { - expect(message.content).toMatchObject([getWeatherToolUse('Paris')]); + expect(message?.choices?.[0]?.message.tool_calls).toMatchObject([getWeatherToolUse('Paris')]); }); // Second iteration (should be the last) - handleAssistantMessage(getWeatherToolUse('Berlin', 'tool_2')); + handleAssistantMessage([getWeatherToolUse('Berlin', 'tool_2')]); await expectEvent(iterator, (message) => { - expect(message.content).toMatchObject([getWeatherToolUse('Berlin', 'tool_2')]); + expect(message?.choices?.[0]?.message.tool_calls).toMatchObject([ + getWeatherToolUse('Berlin', 'tool_2'), + ]); }); // Should stop here due to max_iterations @@ -639,7 +654,7 @@ describe('ToolRunner', () => { expect(messages).toHaveLength(5); await expect(runner.runUntilDone()).resolves.toMatchObject({ role: 'assistant', - content: [getWeatherToolUse('Berlin', 'tool_2')], + tool_calls: [getWeatherToolUse('Berlin', 'tool_2')], }); }); }); @@ -650,7 +665,7 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); - handleAssistantMessage(getWeatherToolUse('SF')); + handleAssistantMessage([getWeatherToolUse('SF')]); // Get first message await expectEvent(iterator); @@ -754,7 +769,7 @@ describe('ToolRunner', () => { handleAssistantMessage(getTextContent()); const finalMessage = await runner.runUntilDone(); - expect(finalMessage.content[0]).toMatchObject(getTextContent()); + expect(finalMessage).toMatchObject(getTextContent()); }); }); @@ -773,7 +788,7 @@ describe('ToolRunner', () => { handleAssistantMessage(getTextContent()); const finalMessage = await runner.done(); - expect(finalMessage.content[0]).toMatchObject(getTextContent()); + expect(finalMessage).toMatchObject(getTextContent()); await consumePromise; }); @@ -788,11 +803,25 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); // First message create call should respond with a tool use. - handleAssistantMessage(getWeatherToolUse('Miami')); - await iterator.next(); - // When we call generateToolResponse, assert that we respond with the tool result. - const toolResponse = await runner.generateToolResponse(); - expect(toolResponse).toMatchObject({ role: 'user', content: [getWeatherToolResult('Miami')] }); + handleAssistantMessage([getWeatherToolUse('Miami')]); + const firstResult = await iterator.next(); + // Make sure we got the message + expect(firstResult.value).toMatchObject({ + choices: [ + { + message: { + role: 'assistant', + content: null, + refusal: null, + tool_calls: [getWeatherToolUse('Miami')], + }, + }, + ], + }); + + // When we call generateToolResponse, it should use the previous message + const toolResponse = await runner.generateToolResponse(); // this is the cached prev tool response (aka Miami weather) + expect(toolResponse?.[0]).toMatchObject(getWeatherToolResult('Miami')); // At this point we should still only have the initial user message // The assistant message gets added after the yield completes expect(runner.params.messages.length).toBe(1); @@ -803,7 +832,7 @@ describe('ToolRunner', () => { await expectDone(iterator); }); - it('calls tools at most once', async () => { + it.skip('calls tools at most once', async () => { let weatherToolCallCount = 0; const trackingWeatherTool: BetaRunnableTool<{ location: string }> = { type: 'function', @@ -827,7 +856,7 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); // Assistant requests tool - handleAssistantMessage(getWeatherToolUse('Boston')); + handleAssistantMessage([getWeatherToolUse('Boston')]); await iterator.next(); // Tools are executed automatically in the ToolRunner after receiving tool_use blocks @@ -858,7 +887,7 @@ describe('ToolRunner', () => { expect(weatherToolCallCount).toBe(1); }); - it('returns null when no tools need execution', async () => { + it.skip('returns null when no tools need execution', async () => { const { runner, handleAssistantMessage } = setupTest({ messages: [{ role: 'user', content: 'Just chat' }], }); diff --git a/tests/lib/tools/nockFixtures/ToolRunner.json b/tests/lib/tools/nockFixtures/ToolRunner.json index 5a15ef5be..89c2ea927 100644 --- a/tests/lib/tools/nockFixtures/ToolRunner.json +++ b/tests/lib/tools/nockFixtures/ToolRunner.json @@ -1,474 +1,474 @@ [ - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "value": { + "type": "string" } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "value": { - "type": "string" - } - } - } - } - } - ], - "stream": false - }, - "status": 200, - "response": [ - "1b3404201c07ce392f9674370bc94efe64815e55fdd411cb03dfd840a050cf2b7479e5956869eb28b0f43db8dc3fbf2db4986eb607beb7b91f131b3c45c3b28453ca361b41a33e11419d36a7a73dab77eb50ec0144f2676e5e65ec2e7e8e1fddefc93c885f77d12593efbb9b2970a565d898cfd8d0104531f4010924c1fd7c06a2ae29ba600a82baa18d306f8755c72a259ba65356308e4d6de3fc37777f06febea0712f81c05ce4514c406e8b9a329b3a88fb11864b86f5617918038634885adab74df99faaab40f61f28fd3c26ce97adc9dfb5f1f4ba3d1efdc22d859718d30262c122e18b13514847128621b8a00ee45d525796590b2d1a66105dacbf08b1ff0b4feff917c77af13a2daf37f887062fd8999b42d4c4d6dad6b990bc949561d5944eabddac0235295d8ca8c39bd9c2569cd6c7b45bb5fa79d551b2efb54093e6528c0be19ea8608a84204fd7a2376c11ffc39e6f94e12d4f26ca36ccee304696c7db93f6f6e480abe322dc159382d0a2e743a89ba824bfa8a92275b3759cf587d4c57e03504711a7bad0a237f860b941fa7ead48334cc7f60cdfb4d105" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbb91b9d442f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:45 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "332", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=lpPj9JFyqlPPHP_HkoosAVe0qXpd8Sv7nn2TbPz.7XU-1764709005788-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "648", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999974", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_f2c619799e6a49df915d7151b34af812" - }, - "responseIsBinary": false + } + } + } + } + ], + "stream": false }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." - }, - { - "role": "assistant", - "content": null, - "tool_calls": [ - { - "id": "call_kXFjbYa63Zq8QTBFFenco0Si", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"value\":\"test\"}" - } - } - ], - "refusal": null, - "annotations": [] - }, - { - "role": "tool", - "content": "Tool result", - "tool_call_id": "call_kXFjbYa63Zq8QTBFFenco0Si" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "value": { - "type": "string" - } - } - } - } - } - ], - "stream": false - }, - "status": 200, - "response": [ - "1b6603081c056eacc77324e1504f6156da56b599addfbcc35ad5bc0970c1ac411494fab6820e4b57ffffaf768687561aa1c063f9dbf2da16d174bd53bb15771248c3b284b3989b591b471afd303be6a72f0c558a603bff961cc541ee54e36a48c3a2d77fce75db6b3e5df25b6bb47cf5ec76b030cc534bc3271224a68c7d4774d7b15ccdd734bb1603e5d162216eb245b2adce64cdeb46a7564e20996fa8ea2f019367fe4493186a2a4304ab946f10376336ff0683d4cc794ed3a75d6607f6942046dffb945d0e91f22b6df15dcc0edb8a17819c4831a17e03984507410e00605bc5e4e865f73f9db70e54880bc5571511d61bf9514b3c0ee310d216d86e5ddf576209e2424771e314e18a479e935c609f00aa745b1c2c643fd27429247e6c70dd03884129d8dc24410a04e4f8778fead03ee4023c599d8a16016d47c4dd2acebc81abe78dda328b9dfe155936f9adca2e08dc8f80249d88df7c23ac94a3bf73c11dcf8fa3d4cbfc080e" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbb966db942f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:46 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "453", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=dIQGF8J5UWhZ4SvG6kU7vUjxKahEtpjMKX7lCEQJmWA-1764709006362-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "470", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999969", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_94e15302a82b469cb4d179718e715ba0" - }, - "responseIsBinary": false + "status": 200, + "response": [ + "1b3404201c07ce392f9674370bc94efe64815e55fdd411cb03dfd840a050cf2b7479e5956869eb28b0f43db8dc3fbf2db4986eb607beb7b91f131b3c45c3b28453ca361b41a33e11419d36a7a73dab77eb50ec0144f2676e5e65ec2e7e8e1fddefc93c885f77d12593efbb9b2970a565d898cfd8d0104531f4010924c1fd7c06a2ae29ba600a82baa18d306f8755c72a259ba65356308e4d6de3fc37777f06febea0712f81c05ce4514c406e8b9a329b3a88fb11864b86f5617918038634885adab74df99faaab40f61f28fd3c26ce97adc9dfb5f1f4ba3d1efdc22d859718d30262c122e18b13514847128621b8a00ee45d525796590b2d1a66105dacbf08b1ff0b4feff917c77af13a2daf37f887062fd8999b42d4c4d6dad6b990bc949561d5944eabddac0235295d8ca8c39bd9c2569cd6c7b45bb5fa79d551b2efb54093e6528c0be19ea8608a84204fd7a2376c11ffc39e6f94e12d4f26ca36ccee304696c7db93f6f6e480abe322dc159382d0a2e743a89ba824bfa8a92275b3759cf587d4c57e03504711a7bad0a237f860b941fa7ead48334cc7f60cdfb4d105" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbb91b9d442f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:45 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "332", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=lpPj9JFyqlPPHP_HkoosAVe0qXpd8Sv7nn2TbPz.7XU-1764709005788-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "648", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999974", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_f2c619799e6a49df915d7151b34af812" }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "count": { - "type": "number" - } - } - } - } - } - ], - "stream": false + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." }, - "status": 200, - "response": [ - "1b1205601c0776d356336ef452185b7fa2989c27747bf5885a1bdb4a7d19d3c8f1223edcdf538745e18f7b779fe3d0c2147abb318777f19e1e25169695684a89628b6ec24c3f62d29e6ccf6e287400c8e3d7ecb448483ddc84eba0eb95ac3ed07c39163efadc6ea7eac1daacd6f09083ca36f6f311182f5a5e03ac2c0932a3328cf4260bf1d4ef170d29e46493d64946210ffc96ee773e5d076e80bc76b20c01121f7280aa4899e90190f53318abfd95a4c6c731581f418cae6996e7fa6d58a090f217509905c754284ec38b255ffaa3fd32bb74b3bdc9c33c585678d5e44d233084f9318ec4d42233966e108db4a75d2dc94858fade2ae0e02df097ff88cfbf8dc3f7f16f81df6a617c5905523c49fc8fa46d4b2be2c7fc7af19ab3757d132dffd5d0779a5101635d47e76b5ba41e2bc9fda2caad9a37dce01ac691c099a8a54896b00d97b5e51aafb8b5d2a2c1716ca00624e5b456338d61dd8240dd3f86b8c7b21c212f82bd3d1ef250a357c4a198ec241ab9c6316cf87473e615cefedf1c66fed7303ad84570ee132553e96427541e59945d2f23da3036a15b0130471096c7bc08ee9d888652aadbb705ba0aabbabcc02b16f401" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbb99e86742f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:47 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "1458", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=qi330.nZqpWAjkxgfpHpx2xbkc2UcZcgIVqzaBpJOJc-1764709007921-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "1470", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999973", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_5d9e0413b7b942aeb8212d70c86dc374" + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_kXFjbYa63Zq8QTBFFenco0Si", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"value\":\"test\"}" + } + } + ], + "refusal": null, + "annotations": [] }, - "responseIsBinary": false - }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" - }, - { - "role": "assistant", - "content": null, - "tool_calls": [ - { - "id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"count\": 1}" - } - }, - { - "id": "call_3SAikZPh6kJlgz6ASqbj3I3Q", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"count\": 2}" - } - } - ], - "refusal": null, - "annotations": [] - }, - { - "role": "tool", - "content": "Called with 1", - "tool_call_id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3" - }, - { - "role": "tool", - "content": "Called with 2", - "tool_call_id": "call_3SAikZPh6kJlgz6ASqbj3I3Q" + { + "role": "tool", + "content": "Tool result", + "tool_call_id": "call_kXFjbYa63Zq8QTBFFenco0Si" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "value": { + "type": "string" } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "count": { - "type": "number" - } - } - } - } - } - ], - "stream": false - }, - "status": 200, - "response": [ - "1b4903201c056eacc77324e150cf1165c4dc52dd7d9e6945bdd9c404681085abbeada0c3d275eae63d4771420b30965fedc18145d15ab6388134cdb4053d8b9111aef1af2f044207811d988d9d1609350f6fe17d71de620ce65e789b66c7eba3f5db6cbd6f8e021602262a84ad1f904030a89c6f84536451613596558f5847b428fb4543893955a619c5aad7967ca4f50ff22707ee8b09bbe198b0e493d48a10e1d1358a0d92a0c67d87c1a9d1684b5ec9815aa9c1bdb56b6d3ffdc0d37881a3a7fff48f35139cf92d582b665873fb7bf7afebab24f78b2ab76a6a0ba569e979040c645a086b1ec47b6d5b333d149b222d1a3dffa535c209e20a516823280b9c361dd0954ab2b4f5a4687bd544dabbceb91d029cf26d18d1bd5fa1b1ec89f137c3cc3fb7614a95d87ad36c1bddc1a4df5e244b7534f3a7a550d79bd0ad1034170c27c562eb5f6b836b106155bd42771d59141cf49226c101" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbba3983a42f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:48 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "570", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=BUCKnZnfZHCGps3vl2nGYAx9wF.sgTuV.Mr9F4AhkTk-1764709008586-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "585", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999963", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_7d1925a5797891a7b7bb58f383b71d92" - }, - "responseIsBinary": false + } + } + } + } + ], + "stream": false }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "input": { - "type": "string" - } - } - } - } + "status": 200, + "response": [ + "1b6603081c056eacc77324e1504f6156da56b599addfbcc35ad5bc0970c1ac411494fab6820e4b57ffffaf768687561aa1c063f9dbf2da16d174bd53bb15771248c3b284b3989b591b471afd303be6a72f0c558a603bff961cc541ee54e36a48c3a2d77fce75db6b3e5df25b6bb47cf5ec76b030cc534bc3271224a68c7d4774d7b15ccdd734bb1603e5d162216eb245b2adce64cdeb46a7564e20996fa8ea2f019367fe4493186a2a4304ab946f10376336ff0683d4cc794ed3a75d6607f6942046dffb945d0e91f22b6df15dcc0edb8a17819c4831a17e03984507410e00605bc5e4e865f73f9db70e54880bc5571511d61bf9514b3c0ee310d216d86e5ddf576209e2424771e314e18a479e935c609f00aa745b1c2c643fd27429247e6c70dd03884129d8dc24410a04e4f8778fead03ee4023c599d8a16016d47c4dd2acebc81abe78dda328b9dfe155936f9adca2e08dc8f80249d88df7c23ac94a3bf73c11dcf8fa3d4cbfc080e" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbb966db942f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:46 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "453", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=dIQGF8J5UWhZ4SvG6kU7vUjxKahEtpjMKX7lCEQJmWA-1764709006362-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "470", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999969", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_94e15302a82b469cb4d179718e715ba0" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "count": { + "type": "number" } - ], - "stream": false + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b1205601c0776d356336ef452185b7fa2989c27747bf5885a1bdb4a7d19d3c8f1223edcdf538745e18f7b779fe3d0c2147abb318777f19e1e25169695684a89628b6ec24c3f62d29e6ccf6e287400c8e3d7ecb448483ddc84eba0eb95ac3ed07c39163efadc6ea7eac1daacd6f09083ca36f6f311182f5a5e03ac2c0932a3328cf4260bf1d4ef170d29e46493d64946210ffc96ee773e5d076e80bc76b20c01121f7280aa4899e90190f53318abfd95a4c6c731581f418cae6996e7fa6d58a090f217509905c754284ec38b255ffaa3fd32bb74b3bdc9c33c585678d5e44d233084f9318ec4d42233966e108db4a75d2dc94858fade2ae0e02df097ff88cfbf8dc3f7f16f81df6a617c5905523c49fc8fa46d4b2be2c7fc7af19ab3757d132dffd5d0779a5101635d47e76b5ba41e2bc9fda2caad9a37dce01ac691c099a8a54896b00d97b5e51aafb8b5d2a2c1716ca00624e5b456338d61dd8240dd3f86b8c7b21c212f82bd3d1ef250a357c4a198ec241ab9c6316cf87473e615cefedf1c66fed7303ad84570ee132553e96427541e59945d2f23da3036a15b0130471096c7bc08ee9d888652aadbb705ba0aabbabcc02b16f401" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbb99e86742f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:47 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "1458", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=qi330.nZqpWAjkxgfpHpx2xbkc2UcZcgIVqzaBpJOJc-1764709007921-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "1470", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999973", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_5d9e0413b7b942aeb8212d70c86dc374" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" }, - "status": 200, - "response": [ - "1b3404201c07ce392f9674370bc94efe64819ed37e73c4b9103ead4353a8e715babcf24ab4b4751458fafefce5ee385b6831f4e66f0f3c6f73372636788a866509a7946d3522d8a53e11418db6ae8ef6ecee5d3b64bf0122f9b3971f796cc75edb9b57642741a771627d3fdf4ffaf96fa0652b63696343535445cf0f48600919e73310754dd10553108c9d6cc4b6fd8b325609d9349db282716e6abbe4bfbd7b19f8c782e6bd04027353663101b92d4a426fe920ee4718ae19d687e55e0c19d2206a99b1f364ffa57115cafe0365b3774739471d63775ad6ddbc7614d9eeb83b13d34262e1aae10b123190998917c6e0a23a92774959187addb39a30a3e8a2bd22e8ce159edef315c776f1baccae37e40f0d565a889b3cd4a4dedadeb990bce485bf28099fa976b30ad4a474b1fc0e6f668b58715a1ed36ed1e6f85146c9be97024d6c9918e7c14ba24229e2814abaea7f608bf8eff57ca30c6fbd65fc6ca3ecf6626c79b03d511fcf0eb8da0e7e87c1b420b4e8fde019c62f291f6a2acbb8397792f58794d99f04a08e12ce75a1455ff0a17243f4fd1ad1c710cd8facc8c6135d" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbba86c8b42f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:49 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "985", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=oJb88Mguy0KPy3QsA56AonUav8eXZp4Vndi.eTdWPoE-1764709009776-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "1002", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999976", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_dc3243bab67944a1b586d7a40f600776" + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"count\": 1}" + } + }, + { + "id": "call_3SAikZPh6kJlgz6ASqbj3I3Q", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"count\": 2}" + } + } + ], + "refusal": null, + "annotations": [] }, - "responseIsBinary": false - }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" - }, - { - "role": "assistant", - "content": null, - "tool_calls": [ - { - "id": "call_tMdC4ZpC8UYPyDuyj43iCkU9", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"input\":\"test\"}" - } - } - ], - "refusal": null, - "annotations": [] - }, - { - "role": "tool", - "content": "Tool result", - "tool_call_id": "call_tMdC4ZpC8UYPyDuyj43iCkU9" + { + "role": "tool", + "content": "Called with 1", + "tool_call_id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3" + }, + { + "role": "tool", + "content": "Called with 2", + "tool_call_id": "call_3SAikZPh6kJlgz6ASqbj3I3Q" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "count": { + "type": "number" } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "input": { - "type": "string" - } - } - } - } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b4903201c056eacc77324e150cf1165c4dc52dd7d9e6945bdd9c404681085abbeada0c3d275eae63d4771420b30965fedc18145d15ab6388134cdb4053d8b9111aef1af2f044207811d988d9d1609350f6fe17d71de620ce65e789b66c7eba3f5db6cbd6f8e021602262a84ad1f904030a89c6f84536451613596558f5847b428fb4543893955a619c5aad7967ca4f50ff22707ee8b09bbe198b0e493d48a10e1d1358a0d92a0c67d87c1a9d1684b5ec9815aa9c1bdb56b6d3ffdc0d37881a3a7fff48f35139cf92d582b665873fb7bf7afebab24f78b2ab76a6a0ba569e979040c645a086b1ec47b6d5b333d149b222d1a3dffa535c209e20a516823280b9c361dd0954ab2b4f5a4687bd544dabbceb91d029cf26d18d1bd5fa1b1ec89f137c3cc3fb7614a95d87ad36c1bddc1a4df5e244b7534f3a7a550d79bd0ad1034170c27c562eb5f6b836b106155bd42771d59141cf49226c101" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbba3983a42f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:48 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "570", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=BUCKnZnfZHCGps3vl2nGYAx9wF.sgTuV.Mr9F4AhkTk-1764709008586-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "585", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999963", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_7d1925a5797891a7b7bb58f383b71d92" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "input": { + "type": "string" } - ], - "stream": false + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b3404201c07ce392f9674370bc94efe64819ed37e73c4b9103ead4353a8e715babcf24ab4b4751458fafefce5ee385b6831f4e66f0f3c6f73372636788a866509a7946d3522d8a53e11418db6ae8ef6ecee5d3b64bf0122f9b3971f796cc75edb9b57642741a771627d3fdf4ffaf96fa0652b63696343535445cf0f48600919e73310754dd10553108c9d6cc4b6fd8b325609d9349db282716e6abbe4bfbd7b19f8c782e6bd04027353663101b92d4a426fe920ee4718ae19d687e55e0c19d2206a99b1f364ffa57115cafe0365b3774739471d63775ad6ddbc7614d9eeb83b13d34262e1aae10b123190998917c6e0a23a92774959187addb39a30a3e8a2bd22e8ce159edef315c776f1baccae37e40f0d565a889b3cd4a4dedadeb990bce485bf28099fa976b30ad4a474b1fc0e6f668b58715a1ed36ed1e6f85146c9be97024d6c9918e7c14ba24229e2814abaea7f608bf8eff57ca30c6fbd65fc6ca3ecf6626c79b03d511fcf0eb8da0e7e87c1b420b4e8fde019c62f291f6a2acbb8397792f58794d99f04a08e12ce75a1455ff0a17243f4fd1ad1c710cd8facc8c6135d" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbba86c8b42f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:49 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "985", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=oJb88Mguy0KPy3QsA56AonUav8eXZp4Vndi.eTdWPoE-1764709009776-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "1002", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999976", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_dc3243bab67944a1b586d7a40f600776" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" }, - "status": 200, - "response": [ - "1b2303201c076eac66e4a0959313a8725ea1a6ea277ab6b4add4974f1cc86fd1930ef7d4615198ba79cf6dce3496ff6f4f0ea4eb7c2d4b274918269c8a6e88495279076f8f56a54090e46f4937b6f4503daa57b2cc7be44517af39c5f2f1be5f57a10e8b27603488f2858d0f4810cf909e53044acf99260f84086afc8e282b17e34acd40cd34a5c29f9bae97ec1f641fecf84723dc308e05d929a148c079256d1edad801b96fe0e3126854ef949683f41b7f5cd462b56e640d81e0d7b22e71f6228fdaa118e7215eae36b33b139504e8a0460154c2cc38c0eb0d83db58e5ddb8a272a37b86be2d1631dc386ea90c6b44f332ca6bdfcf427137f93252682b3da74d2e56e6e631f1c5bb5f67e8ed45e437abbe189bc764fdb7d01d3621b7ce94c22512a4b04c4c52f22aae553603c16de0e3a2195818600db62e74d6773e62e6cb20d346fb313400" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbbaf5bd142f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:50 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "422", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=cePexYFkijPVWrWqH3vLF2RIg.1dy1YjD_.Dp8_n7Nk-1764709010314-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "435", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999971", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_4e047e9ec0344280be4d034850f217b5" + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_tMdC4ZpC8UYPyDuyj43iCkU9", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"input\":\"test\"}" + } + } + ], + "refusal": null, + "annotations": [] }, - "responseIsBinary": false - } -] \ No newline at end of file + { + "role": "tool", + "content": "Tool result", + "tool_call_id": "call_tMdC4ZpC8UYPyDuyj43iCkU9" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "input": { + "type": "string" + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b2303201c076eac66e4a0959313a8725ea1a6ea277ab6b4add4974f1cc86fd1930ef7d4615198ba79cf6dce3496ff6f4f0ea4eb7c2d4b274918269c8a6e88495279076f8f56a54090e46f4937b6f4503daa57b2cc7be44517af39c5f2f1be5f57a10e8b27603488f2858d0f4810cf909e53044acf99260f84086afc8e282b17e34acd40cd34a5c29f9bae97ec1f641fecf84723dc308e05d929a148c079256d1edad801b96fe0e3126854ef949683f41b7f5cd462b56e640d81e0d7b22e71f6228fdaa118e7215eae36b33b139504e8a0460154c2cc38c0eb0d83db58e5ddb8a272a37b86be2d1631dc386ea90c6b44f332ca6bdfcf427137f93252682b3da74d2e56e6e631f1c5bb5f67e8ed45e437abbe189bc764fdb7d01d3621b7ce94c22512a4b04c4c52f22aae553603c16de0e3a2195818600db62e74d6773e62e6cb20d346fb313400" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a7dbbaf5bd142f8-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Tue, 02 Dec 2025 20:56:50 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "422", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=cePexYFkijPVWrWqH3vLF2RIg.1dy1YjD_.Dp8_n7Nk-1764709010314-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "435", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999971", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_4e047e9ec0344280be4d034850f217b5" + }, + "responseIsBinary": false + } +] From d224d002031890e14f74e56586f0cb5e258baaa3 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 00:02:06 -0500 Subject: [PATCH 11/43] most tests passing --- tests/lib/tools/ToolRunner.test.ts | 334 +++++++++++++++++------------ 1 file changed, 192 insertions(+), 142 deletions(-) diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index e0b09609e..c1c8cec65 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -9,11 +9,11 @@ import { ChatCompletion, ChatCompletionChunk, ChatCompletionMessage, + ChatCompletionMessageFunctionToolCall, ChatCompletionMessageToolCall, ChatCompletionToolMessageParam, } from 'openai/resources'; import { Fetch } from 'openai/internal/builtin-types'; -import { ChatCompletionStream } from 'openai/lib/ChatCompletionStream'; const weatherTool: BetaRunnableTool<{ location: string }> = { type: 'function', @@ -114,110 +114,168 @@ function getTextContent(text?: string): ChatCompletionMessage { }; } -function betaMessageToStreamEvents(message: BetaMessage): BetaRawMessageStreamEvent[] { - const events: BetaRawMessageStreamEvent[] = []; +function betaMessageToStreamEvents(message: ChatCompletion): ChatCompletionChunk[] { + const events: ChatCompletionChunk[] = []; - events.push({ - type: 'message_start', - message: { + const messageContent = message.choices[0]!.message; + + // Check if it's a text message + if (messageContent.content && typeof messageContent.content === 'string') { + // Initial chunk with role only (no content in first chunk for text messages) + events.push({ + choices: message.choices.map( + (choice): ChatCompletionChunk.Choice => ({ + delta: { + content: null, + refusal: null, + role: choice.message.role, + }, + finish_reason: null, + index: choice.index, + }), + ), id: message.id, - type: message.type, - role: message.role, + created: message.created, model: message.model, - content: [], - stop_reason: null, - stop_sequence: null, - container: null, - context_management: null, - usage: { - cache_creation: null, - cache_creation_input_tokens: null, - cache_read_input_tokens: null, - input_tokens: message.usage.input_tokens, - output_tokens: 0, - server_tool_use: null, - service_tier: null, - }, - }, - }); - - message.content.forEach((block, index) => { - if (block.type === 'text') { - events.push({ - type: 'content_block_start', - index, - content_block: { type: 'text', text: '', citations: null }, - }); + object: 'chat.completion.chunk', + }); - // Text deltas - always chunked - // Simulate chunked streaming by splitting text - const words = block.text.split(' '); - const chunks = []; - for (let i = 0; i < words.length; i += 2) { - chunks.push(words.slice(i, i + 2).join(' ') + (i + 2 < words.length ? ' ' : '')); - } - chunks.forEach((chunk) => { - if (chunk) { - events.push({ - type: 'content_block_delta', - index, - delta: { type: 'text_delta', text: chunk }, - }); - } - }); - } else if (block.type === 'tool_use') { - events.push({ - type: 'content_block_start', - index, - content_block: { - type: 'tool_use', - id: block.id, - name: block.name, - input: '', - }, - }); + // Text deltas - always chunked + // Simulate chunked streaming by splitting text + const words = messageContent.content.split(' '); + const chunks = []; + for (let i = 0; i < words.length; i += 2) { + chunks.push(words.slice(i, i + 2).join(' ') + (i + 2 < words.length ? ' ' : '')); + } - // Input JSON deltas - always chunked - const jsonStr = JSON.stringify(block.input); - // Simulate chunked JSON streaming - const chunkSize = Math.ceil(jsonStr.length / 3); - for (let i = 0; i < jsonStr.length; i += chunkSize) { + // Create a chunk for each piece of text + chunks.forEach((chunk) => { + if (chunk) { events.push({ - type: 'content_block_delta', - index, - delta: { - type: 'input_json_delta', - partial_json: jsonStr.slice(i, i + chunkSize), - }, + choices: [ + { + delta: { + content: chunk, + refusal: null, + }, + index: 0, + finish_reason: null, + }, + ], + id: message.id, + created: message.created, + model: message.model, + object: 'chat.completion.chunk', }); } - } - + }); + } else if (messageContent.tool_calls && messageContent.tool_calls.length > 0) { + // Initial chunk with role only for tool calls events.push({ - type: 'content_block_stop', - index, + choices: message.choices.map( + (choice): ChatCompletionChunk.Choice => ({ + delta: { + content: null, + refusal: null, + role: choice.message.role, + }, + finish_reason: null, + index: choice.index, + }), + ), + id: message.id, + created: message.created, + model: message.model, + object: 'chat.completion.chunk', }); - }); - events.push({ - type: 'message_delta', - delta: { - stop_reason: message.stop_reason, - container: message.container, - stop_sequence: message.stop_sequence, - }, - context_management: null, - usage: { - output_tokens: message.usage?.output_tokens || 0, - input_tokens: message.usage?.input_tokens || 0, - cache_creation_input_tokens: null, - cache_read_input_tokens: null, - server_tool_use: null, - }, - }); + // Handle tool calls + messageContent.tool_calls.forEach((toolCall, toolIndex) => { + // Initial tool call chunk + if (toolCall.type === 'function') { + const functionToolCall = toolCall as ChatCompletionMessageFunctionToolCall; + + // Create a chunk for the function name + events.push({ + choices: [ + { + delta: { + tool_calls: [ + { + index: toolIndex, + id: toolCall.id, + type: 'function', + function: { + name: functionToolCall.function.name, + }, + }, + ], + content: null, + refusal: null, + }, + index: 0, + finish_reason: null, + }, + ], + id: message.id, + created: message.created, + model: message.model, + object: 'chat.completion.chunk', + }); + + // Input JSON deltas - always chunked for arguments + const jsonStr = functionToolCall.function.arguments; + // Simulate chunked JSON streaming + const chunkSize = Math.ceil(jsonStr.length / 3); + for (let i = 0; i < jsonStr.length; i += chunkSize) { + const argChunk = jsonStr.slice(i, i + chunkSize); + events.push({ + choices: [ + { + delta: { + tool_calls: [ + { + index: toolIndex, + function: { + arguments: argChunk, + }, + }, + ], + content: null, + refusal: null, + }, + index: 0, + finish_reason: null, + }, + ], + id: message.id, + created: message.created, + model: message.model, + object: 'chat.completion.chunk', + }); + } + } + }); + } + // Final chunk with finish reason events.push({ - type: 'message_stop', + choices: [ + { + delta: { + content: null, + role: 'assistant', + refusal: null, + }, + index: 0, + finish_reason: message.choices[0]!.finish_reason, + }, + ], + id: message.id, + created: message.created, + model: message.model, + object: 'chat.completion.chunk', + usage: message.usage ?? null, }); return events; @@ -228,8 +286,8 @@ interface SetupTestResult { runner: OpenAI.Beta.Chat.Completions.BetaToolRunner; fetch: ReturnType['fetch']; handleRequest: (fetch: Fetch) => void; - handleAssistantMessage: (firstChoice: ToolCallsOrMessage) => ChatCompletion; - handleAssistantMessageStream: (toolCalls?: ChatCompletionChunk[]) => ChatCompletionStream; + handleAssistantMessage: (messageContentOrToolCalls: ToolCallsOrMessage) => ChatCompletion; + handleAssistantMessageStream: (messageContentOrToolCalls?: ToolCallsOrMessage) => ChatCompletion; } type ToolRunnerParams = Parameters[0]; @@ -241,7 +299,6 @@ function setupTest(params: Partial & { stream: true }): SetupT function setupTest(params: Partial = {}): SetupTestResult { const { handleRequest, handleStreamEvents, fetch } = mockFetch(); let messageIdCounter = 0; - const handleAssistantMessage: SetupTestResult['handleAssistantMessage'] = ( messageContentOrToolCalls, ) => { @@ -286,11 +343,20 @@ function setupTest(params: Partial = {}): SetupTestResult['handleAssistantMessageStream'] = (...chunks) => { - const hasToolUse = chunks.some( - (chunk) => (chunk?.at(0)?.choices?.at(0)?.delta?.tool_calls?.length ?? 0) > 0, - ); - const stop_reason = hasToolUse ? 'tool_use' : 'end_turn'; + const handleAssistantMessageStream: SetupTestResult['handleAssistantMessageStream'] = ( + messageContentOrToolCalls, + ) => { + const isToolCalls = Array.isArray(messageContentOrToolCalls); + + const messageContent = + isToolCalls ? + { + role: 'assistant' as const, + tool_calls: messageContentOrToolCalls, + refusal: null, + content: null, + } + : (messageContentOrToolCalls as ChatCompletionMessage); const message: ChatCompletion = { id: `msg_${messageIdCounter++}`, @@ -300,12 +366,8 @@ function setupTest(params: Partial = {}): SetupTestResult = {}): SetupTestResult { const iterator = runner[Symbol.asyncIterator](); // First iteration: assistant requests tool (using helper that generates proper stream events) - handleAssistantMessageStream(getWeatherToolUse('SF')); + handleAssistantMessageStream([getWeatherToolUse('SF')]); await expectEvent(iterator, async (stream) => { - expect(stream.constructor.name).toBe('BetaMessageStream'); + expect(stream.constructor.name).toBe('ChatCompletionStream'); const events = []; for await (const event of stream) { events.push(event); @@ -415,15 +477,15 @@ describe('ToolRunner', () => { expect(result2.done).toBe(false); const stream2 = result2.value; - const events2 = []; + const events2: ChatCompletionChunk[] = []; for await (const event of stream2) { events2.push(event); } // With chunked text, we'll get multiple text_delta events - expect(events2.length).toBeGreaterThanOrEqual(6); - const textDeltas = events2.filter((e) => e.type === 'content_block_delta'); - expect(textDeltas.length).toBeGreaterThanOrEqual(1); + // expect(events2.length).toBeGreaterThanOrEqual(6); + // const textDeltas = events2.filter((e) => e.type === 'content_block_delta'); + // expect(textDeltas.length).toBeGreaterThanOrEqual(1); await expectDone(iterator); }); @@ -593,7 +655,7 @@ describe('ToolRunner', () => { handleAssistantMessageStream(getTextContent()); const iterator2 = runner[Symbol.asyncIterator](); await expectEvent(iterator2, (message) => { - expect(message.finalMessage()).resolves.toMatchObject({ content: [getTextContent()] }); + expect(message.finalMessage()).resolves.toMatchObject(getTextContent()); }); await expectDone(iterator2); }); @@ -699,7 +761,7 @@ describe('ToolRunner', () => { handleAssistantMessage(getTextContent()); await expectEvent(iterator, (message) => { - expect(message.content[0]).toMatchObject(getTextContent()); + expect(message?.choices[0]?.message).toMatchObject(getTextContent()); }); // Verify params were updated @@ -717,31 +779,28 @@ describe('ToolRunner', () => { const iterator = runner[Symbol.asyncIterator](); // First iteration: assistant requests tool - handleAssistantMessage(getWeatherToolUse('Paris')); + handleAssistantMessage([getWeatherToolUse('Paris')]); await expectEvent(iterator, (message) => { - expect(message.content).toMatchObject([getWeatherToolUse('Paris')]); + expect(message?.choices[0]?.message?.tool_calls).toMatchObject([getWeatherToolUse('Paris')]); }); // Verify generateToolResponse returns the tool result for Paris const toolResponse = await runner.generateToolResponse(); - expect(toolResponse).toMatchObject({ - role: 'user', - content: [getWeatherToolResult('Paris')], - }); + expect(toolResponse).toMatchObject([getWeatherToolResult('Paris')]); // Update params to append a custom tool_use block to messages - runner.setMessagesParams((params) => ({ - ...params, + runner.setMessagesParams({ + ...runner.params, messages: [ - ...params.messages, - { role: 'assistant', content: [getWeatherToolUse('London', 'tool_2')] }, + ...runner.params.messages, + { role: 'assistant', tool_calls: [getWeatherToolUse('London', 'tool_1')] }, ], - })); + }); // Assistant provides final response incorporating both tool results handleAssistantMessage(getTextContent()); await expectEvent(iterator, (message) => { - expect(message.content[0]).toMatchObject(getTextContent()); + expect(message?.choices[0]?.message).toMatchObject(getTextContent()); }); // Verify the messages were properly appended @@ -749,14 +808,11 @@ describe('ToolRunner', () => { expect(runner.params.messages).toHaveLength(3); expect(runner.params.messages[1]).toMatchObject({ role: 'assistant', - content: [getWeatherToolUse('London', 'tool_2')], + tool_calls: [getWeatherToolUse('London', 'tool_1')], }); // Verify the third message has the London tool_result // (responded to automatically by the ToolRunner) - expect(runner.params.messages[2]).toMatchObject({ - role: 'user', - content: [getWeatherToolResult('London', 'tool_2')], - }); + expect(runner.params.messages[2]).toMatchObject(getWeatherToolResult('Paris', 'tool_1')); await expectDone(iterator); }); }); @@ -832,7 +888,7 @@ describe('ToolRunner', () => { await expectDone(iterator); }); - it.skip('calls tools at most once', async () => { + it('calls tools at most once', async () => { let weatherToolCallCount = 0; const trackingWeatherTool: BetaRunnableTool<{ location: string }> = { type: 'function', @@ -864,16 +920,10 @@ describe('ToolRunner', () => { // Let's call it manually to verify caching behavior const response1 = await runner.generateToolResponse(); expect(weatherToolCallCount).toBe(1); // Tool should be called once - expect(response1).toMatchObject({ - role: 'user', - content: [getWeatherToolResult('Boston')], - }); + expect(response1).toMatchObject([getWeatherToolResult('Boston')]); const response2 = await runner.generateToolResponse(); expect(weatherToolCallCount).toBe(1); // Still 1, cached - expect(response2).toMatchObject({ - role: 'user', - content: [getWeatherToolResult('Boston')], - }); + expect(response2).toMatchObject([getWeatherToolResult('Boston')]); // Final response should be an assistant response. handleAssistantMessage(getTextContent()); @@ -887,7 +937,7 @@ describe('ToolRunner', () => { expect(weatherToolCallCount).toBe(1); }); - it.skip('returns null when no tools need execution', async () => { + it('returns null when no tools need execution', async () => { const { runner, handleAssistantMessage } = setupTest({ messages: [{ role: 'user', content: 'Just chat' }], }); From d1fb561d6f3c204eba4b4a3e17061c87fb2af28b Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 10:22:00 -0500 Subject: [PATCH 12/43] add more examples --- examples/tool-helpers-advanced-streaming.ts | 109 ++ examples/tool-helpers-advanced.ts | 38 + examples/tool-helpers-json-schema.ts | 44 + package.json | 1 + src/helpers/beta/betaZodTool.ts | 0 src/helpers/beta/json-schema.ts | 35 + src/lib/beta-parser.ts | 105 -- src/lib/beta/BetaToolRunner.ts | 2 - tests/lib/tools/ToolRunner.test.ts | 2 +- yarn.lock | 1013 +++++++++---------- 10 files changed, 728 insertions(+), 621 deletions(-) create mode 100644 examples/tool-helpers-advanced-streaming.ts create mode 100644 examples/tool-helpers-advanced.ts create mode 100644 examples/tool-helpers-json-schema.ts delete mode 100644 src/helpers/beta/betaZodTool.ts create mode 100644 src/helpers/beta/json-schema.ts delete mode 100644 src/lib/beta-parser.ts diff --git a/examples/tool-helpers-advanced-streaming.ts b/examples/tool-helpers-advanced-streaming.ts new file mode 100644 index 000000000..c110bb43d --- /dev/null +++ b/examples/tool-helpers-advanced-streaming.ts @@ -0,0 +1,109 @@ +#!/usr/bin/env -S npm run tsn -T + +import OpenAI from 'openai'; +import { betaZodTool } from 'openai/helpers/beta/zod'; +import { z } from 'zod'; + +const client = new OpenAI(); + +async function main() { + const runner = client.chat.completions.toolRunner({ + messages: [ + { + role: 'user', + content: `I'm planning a trip to San Francisco and I need some information. Can you help me with the weather, current time, and currency exchange rates (from EUR)? Please use parallel tool use`, + }, + ], + tools: [ + betaZodTool({ + name: 'getWeather', + description: 'Get the weather at a specific location', + inputSchema: z.object({ + location: z.string().describe('The city and state, e.g. San Francisco, CA'), + }), + run: ({ location }) => { + return `The weather is sunny with a temperature of 20°C in ${location}.`; + }, + }), + betaZodTool({ + name: 'getTime', + description: 'Get the current time in a specific timezone', + inputSchema: z.object({ + timezone: z.string().describe('The timezone, e.g. America/Los_Angeles'), + }), + run: ({ timezone }) => { + return `The current time in ${timezone} is 3:00 PM.`; + }, + }), + betaZodTool({ + name: 'getCurrencyExchangeRate', + description: 'Get the exchange rate between two currencies', + inputSchema: z.object({ + from_currency: z.string().describe('The currency to convert from, e.g. USD'), + to_currency: z.string().describe('The currency to convert to, e.g. EUR'), + }), + run: ({ from_currency, to_currency }) => { + return `The exchange rate from ${from_currency} to ${to_currency} is 0.85.`; + }, + }), + ], + model: 'gpt-4o', + max_tokens: 1024, + // This limits the conversation to at most 10 back and forth between the API. + max_iterations: 10, + stream: true, + }); + + console.log(`\nšŸš€ Running tools...\n`); + + let prevMessageStarted = ''; + let prevToolStarted = ''; + let prevWasToolCall = false; + + for await (const messageStream of runner) { + for await (const event of messageStream) { + const hadToolCalls = !!event.choices?.[0]?.delta?.tool_calls; + + if (hadToolCalls) { + if (!prevMessageStarted) { + console.log(`ā”Œā”€ Message ${event.id} `.padEnd(process.stdout.columns, '─')); + prevMessageStarted = event.id; + } + + prevWasToolCall = true; + const toolCalls = event.choices[0]!.delta.tool_calls!; + + for (const toolCall of toolCalls) { + if (toolCall.function?.name && prevToolStarted !== toolCall.function.name) { + process.stdout.write(`\n${toolCall.function.name}: `); + prevToolStarted = toolCall.function.name; + } else if (toolCall.function?.arguments) { + process.stdout.write(toolCall.function.arguments); + } + } + } else if (event.choices?.[0]?.delta?.content) { + if (prevWasToolCall) { + console.log(); + console.log(); + console.log(`└─`.padEnd(process.stdout.columns, '─')); + console.log(); + prevWasToolCall = false; + } + + if (prevMessageStarted !== event.id) { + console.log(`ā”Œā”€ Message ${event.id} `.padEnd(process.stdout.columns, '─')); + console.log(); + prevMessageStarted = event.id; + } + + process.stdout.write(event.choices[0].delta.content); + } + } + } + + console.log(); + console.log(); + console.log(`└─`.padEnd(process.stdout.columns, '─')); +} + +main(); diff --git a/examples/tool-helpers-advanced.ts b/examples/tool-helpers-advanced.ts new file mode 100644 index 000000000..88b6bafff --- /dev/null +++ b/examples/tool-helpers-advanced.ts @@ -0,0 +1,38 @@ +#!/usr/bin/env -S npm run tsn -T + +import OpenAI from 'openai'; +import { betaZodTool } from 'openai/helpers/beta/zod'; +import { z } from 'zod'; + +const client = new OpenAI(); + +async function main() { + const message = await client.chat.completions.toolRunner({ + messages: [ + { + role: 'user', + content: `What is the weather in SF?`, + }, + ], + tools: [ + betaZodTool({ + name: 'getWeather', + description: 'Get the weather at a specific location', + inputSchema: z.object({ + location: z.string().describe('The city and state, e.g. San Francisco, CA'), + }), + run: ({ location }) => { + return `The weather is foggy with a temperature of 20°C in ${location}.`; + }, + }), + ], + model: 'gpt-4o', + max_tokens: 1024, + // the maximum number of iterations to run the tool + max_iterations: 10, + }); + + console.log('Final response:', message.content); +} + +main(); diff --git a/examples/tool-helpers-json-schema.ts b/examples/tool-helpers-json-schema.ts new file mode 100644 index 000000000..81c8d75ec --- /dev/null +++ b/examples/tool-helpers-json-schema.ts @@ -0,0 +1,44 @@ +#!/usr/bin/env -S npm run tsn -T + +import OpenAI from 'openai'; +import { betaTool } from 'openai/helpers/beta/json-schema'; + +const client = new OpenAI(); + +async function main() { + const message = await client.chat.completions.toolRunner({ + messages: [ + { + role: 'user', + content: `What is the weather in SF?`, + }, + ], + tools: [ + betaTool({ + name: 'getWeather', + description: 'Get the weather at a specific location', + inputSchema: { + type: 'object', + properties: { + location: { + type: 'string', + description: 'The city and state, e.g. San Francisco, CA', + }, + }, + required: ['location'], + }, + run: ({ location }) => { + return `The weather is foggy with a temperature of 20°C in ${location}.`; + }, + }), + ], + model: 'gpt-4o', + max_tokens: 1024, + // the maximum number of iterations to run the tool + max_iterations: 10, + }); + + console.log('Final response:', message.content); +} + +main(); diff --git a/package.json b/package.json index e9211895d..e934a2545 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "fix": "./scripts/format" }, "dependencies": { + "json-schema-to-ts": "3.1.1", "nock": "^14.0.10" }, "devDependencies": { diff --git a/src/helpers/beta/betaZodTool.ts b/src/helpers/beta/betaZodTool.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/helpers/beta/json-schema.ts b/src/helpers/beta/json-schema.ts new file mode 100644 index 000000000..a6c85fb0e --- /dev/null +++ b/src/helpers/beta/json-schema.ts @@ -0,0 +1,35 @@ +import type { FromSchema, JSONSchema } from 'json-schema-to-ts'; +import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; +import type { FunctionTool } from '../../resources/beta'; +import { OpenAIError } from '../../error'; + +type NoInfer = T extends infer R ? R : never; + +/** + * Creates a Tool with a provided JSON schema that can be passed + * to the `.toolRunner()` method. The schema is used to automatically validate + * the input arguments for the tool. + */ +export function betaTool & { type: 'object' }>(options: { + name: string; + inputSchema: Schema; + description: string; + run: (args: NoInfer>) => Promisable>; +}): BetaRunnableTool>> { + if (options.inputSchema.type !== 'object') { + throw new OpenAIError( + `JSON schema for tool "${options.name}" must be an object, but got ${options.inputSchema.type}`, + ); + } + + return { + type: 'function', + function: { + name: options.name, + parameters: options.inputSchema, + description: options.description, + }, + run: options.run, + parse: (content: unknown) => content as FromSchema, + } as any; // For some reason this causes infinite inference so we cast to any to not crash lsp +} diff --git a/src/lib/beta-parser.ts b/src/lib/beta-parser.ts deleted file mode 100644 index d418c9862..000000000 --- a/src/lib/beta-parser.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { OpenAIError } from '../core/error'; -import { - BetaContentBlock, - BetaJSONOutputFormat, - BetaMessage, - BetaTextBlock, - MessageCreateParams, -} from '../resources/beta/messages/messages'; - -// vendored from typefest just to make things look a bit nicer on hover -type Simplify = { [KeyType in keyof T]: T[KeyType] } & {}; - -export type BetaParseableMessageCreateParams = Simplify< - Omit & { - output_format?: BetaJSONOutputFormat | AutoParseableBetaOutputFormat | null; - } ->; - -export type ExtractParsedContentFromBetaParams = - Params['output_format'] extends AutoParseableBetaOutputFormat ? P : null; - -export type AutoParseableBetaOutputFormat = BetaJSONOutputFormat & { - parse(content: string): ParsedT; -}; - -export type ParsedBetaMessage = BetaMessage & { - content: Array>; - parsed_output: ParsedT | null; -}; - -export type ParsedBetaContentBlock = - | (BetaTextBlock & { parsed: ParsedT | null }) - | Exclude; - -export function maybeParseBetaMessage( - message: BetaMessage, - params: Params, -): ParsedBetaMessage>> { - if (!params || !('parse' in (params.output_format ?? {}))) { - return { - ...message, - content: message.content.map((block) => { - if (block.type === 'text') { - return { - ...block, - parsed: null, - }; - } - return block; - }), - parsed_output: null, - } as ParsedBetaMessage>>; - } - - return parseBetaMessage(message, params); -} - -export function parseBetaMessage( - message: BetaMessage, - params: Params, -): ParsedBetaMessage> { - let firstParsed: ReturnType> | null = null; - - const content: Array>> = - message.content.map((block) => { - if (block.type === 'text') { - const parsed = parseBetaOutputFormat(params, block.text); - - if (firstParsed === null) { - firstParsed = parsed; - } - - return { - ...block, - parsed, - }; - } - return block; - }); - - return { - ...message, - content, - parsed_output: firstParsed, - } as ParsedBetaMessage>; -} - -function parseBetaOutputFormat( - params: Params, - content: string, -): ExtractParsedContentFromBetaParams | null { - if (params.output_format?.type !== 'json_schema') { - return null; - } - - try { - if ('parse' in params.output_format) { - return params.output_format.parse(content); - } - - return JSON.parse(content); - } catch (error) { - throw new OpenAIError(`Failed to parse structured output: ${error}`); - } -} diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 9178e3e1a..85f1df2ba 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -12,8 +12,6 @@ import type { ChatCompletionToolMessageParam, } from '../../resources/chat/completions'; import type { BetaRunnableTool } from './BetaRunnableTool'; -// BetaMessage, BetaMessageParam, BetaToolUnion, MessageCreateParams -// import { BetaMessageStream } from '../BetaMessageStream'; /** * Just Promise.withResolvers(), which is not available in all environments. diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index c1c8cec65..0bf1ddf0c 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -120,7 +120,7 @@ function betaMessageToStreamEvents(message: ChatCompletion): ChatCompletionChunk const messageContent = message.choices[0]!.message; // Check if it's a text message - if (messageContent.content && typeof messageContent.content === 'string') { + if (messageContent.content) { // Initial chunk with role only (no content in first chunk for text messages) events.push({ choices: message.choices.map( diff --git a/yarn.lock b/yarn.lock index 0276e1b7b..ed41fb0fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4,12 +4,12 @@ "@aashutoshrathi/word-wrap@^1.2.3": version "1.2.6" - resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== "@ampproject/remapping@^2.2.0": version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz" integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== dependencies: "@jridgewell/gen-mapping" "^0.3.0" @@ -17,12 +17,12 @@ "@andrewbranch/untar.js@^1.0.3": version "1.0.3" - resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" + resolved "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz" integrity sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw== "@arethetypeswrong/cli@^0.17.0": version "0.17.0" - resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.17.0.tgz#f97f10926b3f9f9eb5117550242d2e06c25cadac" + resolved "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.17.0.tgz" integrity sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA== dependencies: "@arethetypeswrong/core" "0.17.0" @@ -35,7 +35,7 @@ "@arethetypeswrong/core@0.17.0": version "0.17.0" - resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.17.0.tgz#abb3b5f425056d37193644c2a2de4aecf866b76b" + resolved "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.17.0.tgz" integrity sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA== dependencies: "@andrewbranch/untar.js" "^1.0.3" @@ -48,7 +48,7 @@ "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz" integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== dependencies: "@babel/highlight" "^7.23.4" @@ -56,12 +56,12 @@ "@babel/compat-data@^7.23.5": version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz" integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== "@babel/core@^7.11.6", "@babel/core@^7.12.3": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz" integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== dependencies: "@ampproject/remapping" "^2.2.0" @@ -82,7 +82,7 @@ "@babel/generator@^7.23.6", "@babel/generator@^7.7.2": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz" integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== dependencies: "@babel/types" "^7.23.6" @@ -92,7 +92,7 @@ "@babel/helper-compilation-targets@^7.23.6": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz" integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== dependencies: "@babel/compat-data" "^7.23.5" @@ -103,12 +103,12 @@ "@babel/helper-environment-visitor@^7.22.20": version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== "@babel/helper-function-name@^7.23.0": version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz" integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: "@babel/template" "^7.22.15" @@ -116,21 +116,21 @@ "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: "@babel/types" "^7.22.5" "@babel/helper-module-imports@^7.22.15": version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz" integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== dependencies: "@babel/types" "^7.22.15" "@babel/helper-module-transforms@^7.23.3": version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz" integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== dependencies: "@babel/helper-environment-visitor" "^7.22.20" @@ -141,41 +141,41 @@ "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== "@babel/helper-simple-access@^7.22.5": version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz" integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== dependencies: "@babel/types" "^7.22.5" "@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz" integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== dependencies: "@babel/types" "^7.22.5" "@babel/helper-string-parser@^7.23.4": version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== "@babel/helper-validator-option@^7.23.5": version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== "@babel/helpers@^7.23.6": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz" integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== dependencies: "@babel/template" "^7.22.15" @@ -184,7 +184,7 @@ "@babel/highlight@^7.23.4": version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz" integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== dependencies: "@babel/helper-validator-identifier" "^7.22.20" @@ -193,110 +193,115 @@ "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz" integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-bigint@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz" integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz" integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/runtime@^7.18.3": + version "7.28.4" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz" + integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== + "@babel/template@^7.22.15", "@babel/template@^7.3.3": version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz" integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== dependencies: "@babel/code-frame" "^7.22.13" @@ -305,7 +310,7 @@ "@babel/traverse@^7.23.6": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz" integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== dependencies: "@babel/code-frame" "^7.23.5" @@ -321,7 +326,7 @@ "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz" integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== dependencies: "@babel/helper-string-parser" "^7.23.4" @@ -330,41 +335,41 @@ "@bcoe/v8-coverage@^0.2.3": version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== "@colors/colors@1.5.0": version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + resolved "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz" integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== "@cspotcode/source-map-support@0.7.0": version "0.7.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz" integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== dependencies: "@cspotcode/source-map-consumer" "0.8.0" "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== "@eslint/config-array@^0.19.0": version "0.19.2" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" + resolved "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz" integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== dependencies: "@eslint/object-schema" "^2.1.6" @@ -373,21 +378,21 @@ "@eslint/core@^0.10.0": version "0.10.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" + resolved "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz" integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== dependencies: "@types/json-schema" "^7.0.15" "@eslint/core@^0.11.0": version "0.11.0" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" + resolved "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz" integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== dependencies: "@types/json-schema" "^7.0.15" "@eslint/eslintrc@^3.2.0": version "3.2.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" + resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz" integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== dependencies: ajv "^6.12.4" @@ -402,17 +407,17 @@ "@eslint/js@9.20.0": version "9.20.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" + resolved "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz" integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== "@eslint/object-schema@^2.1.6": version "2.1.6" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz" integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== "@eslint/plugin-kit@^0.2.5": version "0.2.5" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" + resolved "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz" integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== dependencies: "@eslint/core" "^0.10.0" @@ -420,12 +425,12 @@ "@humanfs/core@^0.19.1": version "0.19.1" - resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz" integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== "@humanfs/node@^0.16.6": version "0.16.6" - resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" + resolved "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz" integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== dependencies: "@humanfs/core" "^0.19.1" @@ -433,22 +438,22 @@ "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/retry@^0.3.0": version "0.3.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" + resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== "@humanwhocodes/retry@^0.4.1": version "0.4.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" + resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz" integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" @@ -459,12 +464,12 @@ "@istanbuljs/schema@^0.1.2": version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== "@jest/console@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + resolved "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz" integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== dependencies: "@jest/types" "^29.6.3" @@ -476,7 +481,7 @@ "@jest/core@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + resolved "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz" integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== dependencies: "@jest/console" "^29.7.0" @@ -510,14 +515,14 @@ "@jest/create-cache-key-function@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" + resolved "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz" integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== dependencies: "@jest/types" "^29.6.3" "@jest/environment@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== dependencies: "@jest/fake-timers" "^29.7.0" @@ -527,14 +532,14 @@ "@jest/expect-utils@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz" integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== dependencies: jest-get-type "^29.6.3" "@jest/expect@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + resolved "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz" integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== dependencies: expect "^29.7.0" @@ -542,7 +547,7 @@ "@jest/fake-timers@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== dependencies: "@jest/types" "^29.6.3" @@ -554,7 +559,7 @@ "@jest/globals@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== dependencies: "@jest/environment" "^29.7.0" @@ -564,7 +569,7 @@ "@jest/reporters@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz" integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== dependencies: "@bcoe/v8-coverage" "^0.2.3" @@ -594,14 +599,14 @@ "@jest/schemas@^29.6.3": version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== dependencies: "@sinclair/typebox" "^0.27.8" "@jest/source-map@^29.6.3": version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz" integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== dependencies: "@jridgewell/trace-mapping" "^0.3.18" @@ -610,7 +615,7 @@ "@jest/test-result@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz" integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== dependencies: "@jest/console" "^29.7.0" @@ -620,7 +625,7 @@ "@jest/test-sequencer@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz" integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== dependencies: "@jest/test-result" "^29.7.0" @@ -630,7 +635,7 @@ "@jest/transform@^29.7.0": version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + resolved "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz" integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== dependencies: "@babel/core" "^7.11.6" @@ -651,7 +656,7 @@ "@jest/types@^29.6.3": version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== dependencies: "@jest/schemas" "^29.6.3" @@ -663,7 +668,7 @@ "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz" integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== dependencies: "@jridgewell/set-array" "^1.0.1" @@ -672,22 +677,22 @@ "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== "@jridgewell/set-array@^1.0.1": version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": version "0.3.20" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz" integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== dependencies: "@jridgewell/resolve-uri" "^3.1.0" @@ -695,7 +700,7 @@ "@mswjs/interceptors@^0.39.5": version "0.39.8" - resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.39.8.tgz#0a2cf4cf26a731214ca4156273121f67dff7ebf8" + resolved "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.8.tgz" integrity sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA== dependencies: "@open-draft/deferred-promise" "^2.2.0" @@ -707,7 +712,7 @@ "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -715,12 +720,12 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" @@ -728,12 +733,12 @@ "@open-draft/deferred-promise@^2.2.0": version "2.2.0" - resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" + resolved "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz" integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== "@open-draft/logger@^0.3.0": version "0.3.0" - resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" + resolved "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz" integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== dependencies: is-node-process "^1.2.0" @@ -741,34 +746,34 @@ "@open-draft/until@^2.0.0": version "2.1.0" - resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" + resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz" integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== "@pkgr/core@^0.2.4": version "0.2.4" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" + resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz" integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== "@sinclair/typebox@^0.27.8": version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== "@sindresorhus/is@^4.6.0": version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz" integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== "@sinonjs/commons@^3.0.0": version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" + resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz" integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== dependencies: type-detect "4.0.8" "@sinonjs/fake-timers@^10.0.2": version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== dependencies: "@sinonjs/commons" "^3.0.0" @@ -800,12 +805,12 @@ "@swc/core-linux-x64-gnu@1.4.16": version "1.4.16" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.16.tgz#71eb108b784f9d551ee8a35ebcdaed972f567981" + resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.16.tgz" integrity sha512-UUjaW5VTngZYDcA8yQlrFmqs1tLi1TxbKlnaJwoNhel9zRQ0yG1YEVGrzTvv4YApSuIiDK18t+Ip927bwucuVQ== "@swc/core-linux-x64-musl@1.4.16": version "1.4.16" - resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.16.tgz#10dbaedb4e3dfc7268e3a9a66ad3431471ef035b" + resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.16.tgz" integrity sha512-aFhxPifevDTwEDKPi4eRYWzC0p/WYJeiFkkpNU5Uc7a7M5iMWPAbPFUbHesdlb9Jfqs5c07oyz86u+/HySBNPQ== "@swc/core-win32-arm64-msvc@1.4.16": @@ -825,7 +830,7 @@ "@swc/core@^1.3.102": version "1.4.16" - resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.16.tgz#d175bae2acfecd53bcbd4293f1fba5ec316634a0" + resolved "https://registry.npmjs.org/@swc/core/-/core-1.4.16.tgz" integrity sha512-Xaf+UBvW6JNuV131uvSNyMXHn+bh6LyKN4tbv7tOUFQpXyz/t9YWRE04emtlUW9Y0qrm/GKFCbY8n3z6BpZbTA== dependencies: "@swc/counter" "^0.1.2" @@ -844,12 +849,12 @@ "@swc/counter@^0.1.2", "@swc/counter@^0.1.3": version "0.1.3" - resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" + resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== "@swc/jest@^0.2.29": version "0.2.36" - resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.36.tgz#2797450a30d28b471997a17e901ccad946fe693e" + resolved "https://registry.npmjs.org/@swc/jest/-/jest-0.2.36.tgz" integrity sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw== dependencies: "@jest/create-cache-key-function" "^29.7.0" @@ -858,34 +863,34 @@ "@swc/types@^0.1.5": version "0.1.6" - resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.6.tgz#2f13f748995b247d146de2784d3eb7195410faba" + resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz" integrity sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg== dependencies: "@swc/counter" "^0.1.3" "@tsconfig/node10@^1.0.7": version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz" integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== "@tsconfig/node12@^1.0.7": version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz" integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== "@tsconfig/node14@^1.0.0": version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz" integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== "@tsconfig/node16@^1.0.2": version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== "@types/babel__core@^7.1.14": version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== dependencies: "@babel/parser" "^7.20.7" @@ -896,14 +901,14 @@ "@types/babel__generator@*": version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz" integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz" integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== dependencies: "@babel/parser" "^7.1.0" @@ -911,45 +916,45 @@ "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": version "7.20.4" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.4.tgz#ec2c06fed6549df8bc0eb4615b683749a4a92e1b" + resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz" integrity sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA== dependencies: "@babel/types" "^7.20.7" "@types/estree@^1.0.6": version "1.0.6" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== "@types/graceful-fs@^4.1.3": version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz" integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== dependencies: "@types/node" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz" integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== "@types/istanbul-lib-report@*": version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz" integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz" integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== dependencies: "@types/istanbul-lib-report" "*" "@types/jest@^29.4.0": version "29.5.11" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c" + resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz" integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ== dependencies: expect "^29.0.0" @@ -957,50 +962,43 @@ "@types/json-schema@^7.0.15": version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/node@*": - version "20.10.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" - integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== - dependencies: - undici-types "~5.26.4" - -"@types/node@^20.17.6": +"@types/node@*", "@types/node@^20.17.6": version "20.19.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4" + resolved "https://registry.npmjs.org/@types/node/-/node-20.19.11.tgz" integrity sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow== dependencies: undici-types "~6.21.0" "@types/stack-utils@^2.0.0": version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== "@types/ws@^8.5.13": version "8.5.14" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.14.tgz#93d44b268c9127d96026cf44353725dd9b6c3c21" + resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz" integrity sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw== dependencies: "@types/node" "*" "@types/yargs-parser@*": version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz" integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== dependencies: "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz#62f1befe59647524994e89de4516d8dcba7a850a" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz" integrity sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ== dependencies: "@eslint-community/regexpp" "^4.10.0" @@ -1015,7 +1013,7 @@ "@typescript-eslint/parser@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.1.tgz#e9b0ccf30d37dde724ee4d15f4dbc195995cce1b" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.1.tgz" integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q== dependencies: "@typescript-eslint/scope-manager" "8.31.1" @@ -1026,7 +1024,7 @@ "@typescript-eslint/scope-manager@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz#1eb52e76878f545e4add142e0d8e3e97e7aa443b" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz" integrity sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw== dependencies: "@typescript-eslint/types" "8.31.1" @@ -1034,7 +1032,7 @@ "@typescript-eslint/type-utils@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz#be0f438fb24b03568e282a0aed85f776409f970c" + resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz" integrity sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA== dependencies: "@typescript-eslint/typescript-estree" "8.31.1" @@ -1044,12 +1042,12 @@ "@typescript-eslint/types@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.1.tgz#478ed6f7e8aee1be7b63a60212b6bffe1423b5d4" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.1.tgz" integrity sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ== "@typescript-eslint/typescript-estree@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz#37792fe7ef4d3021c7580067c8f1ae66daabacdf" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz" integrity sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag== dependencies: "@typescript-eslint/types" "8.31.1" @@ -1063,7 +1061,7 @@ "@typescript-eslint/utils@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.1.tgz#5628ea0393598a0b2f143d0fc6d019f0dee9dd14" + resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.1.tgz" integrity sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" @@ -1073,7 +1071,7 @@ "@typescript-eslint/visitor-keys@8.31.1": version "8.31.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz#6742b0e3ba1e0c1e35bdaf78c03e759eb8dd8e75" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz" integrity sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw== dependencies: "@typescript-eslint/types" "8.31.1" @@ -1081,27 +1079,22 @@ acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.14.0: +acorn@^8.14.0, acorn@^8.4.1: version "8.14.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== -acorn@^8.4.1: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" @@ -1109,7 +1102,7 @@ aggregate-error@^3.0.0: ajv@^6.12.4: version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -1119,55 +1112,55 @@ ajv@^6.12.4: ansi-escapes@^4.2.1: version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" ansi-escapes@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" + resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz" integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== dependencies: environment "^1.0.0" ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.1.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz" integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" ansi-styles@^5.0.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== any-promise@^1.0.0: version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== anymatch@^3.0.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -1175,24 +1168,24 @@ anymatch@^3.0.3: arg@^4.1.0: version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== babel-jest@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== dependencies: "@jest/transform" "^29.7.0" @@ -1205,7 +1198,7 @@ babel-jest@^29.7.0: babel-plugin-istanbul@^6.1.1: version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -1216,7 +1209,7 @@ babel-plugin-istanbul@^6.1.1: babel-plugin-jest-hoist@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz" integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== dependencies: "@babel/template" "^7.3.3" @@ -1226,7 +1219,7 @@ babel-plugin-jest-hoist@^29.6.3: babel-preset-current-node-syntax@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" @@ -1244,7 +1237,7 @@ babel-preset-current-node-syntax@^1.0.0: babel-preset-jest@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz" integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== dependencies: babel-plugin-jest-hoist "^29.6.3" @@ -1252,12 +1245,12 @@ babel-preset-jest@^29.6.3: balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -1265,21 +1258,21 @@ brace-expansion@^1.1.7: brace-expansion@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== dependencies: balanced-match "^1.0.0" braces@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" browserslist@^4.22.2: version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz" integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== dependencies: caniuse-lite "^1.0.30001565" @@ -1289,46 +1282,46 @@ browserslist@^4.22.2: bs-logger@0.x: version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + resolved "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== dependencies: fast-json-stable-stringify "2.x" bser@2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: node-int64 "^0.4.0" buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.2.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001565: version "1.0.30001570" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz" integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== chalk@^2.4.2: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -1337,7 +1330,7 @@ chalk@^2.4.2: chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -1345,37 +1338,32 @@ chalk@^4.0.0, chalk@^4.1.2: chalk@^5.3.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + resolved "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== char-regex@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== ci-info@^3.2.0: version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== -cjs-module-lexer@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - -cjs-module-lexer@^1.2.3: +cjs-module-lexer@^1.0.0, cjs-module-lexer@^1.2.3: version "1.4.1" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" + resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz" integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cli-highlight@^2.1.11: version "2.1.11" - resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf" + resolved "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz" integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg== dependencies: chalk "^4.0.0" @@ -1387,7 +1375,7 @@ cli-highlight@^2.1.11: cli-table3@^0.6.3, cli-table3@^0.6.5: version "0.6.5" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" + resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz" integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== dependencies: string-width "^4.2.0" @@ -1396,7 +1384,7 @@ cli-table3@^0.6.3, cli-table3@^0.6.5: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" @@ -1405,7 +1393,7 @@ cliui@^7.0.2: cliui@^8.0.1: version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -1414,56 +1402,56 @@ cliui@^8.0.1: co@^4.6.0: version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== collect-v8-coverage@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== commander@^10.0.1: version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== convert-source-map@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== create-jest@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== dependencies: "@jest/types" "^29.6.3" @@ -1476,12 +1464,12 @@ create-jest@^29.7.0: create-require@^1.1.0: version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" @@ -1490,108 +1478,108 @@ cross-spawn@^7.0.3, cross-spawn@^7.0.6: debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" debug@^4.3.4, debug@^4.3.7: version "4.3.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: ms "^2.1.3" dedent@^1.0.0: version "1.5.1" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + resolved "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz" integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deep-object-diff@^1.1.9: version "1.1.9" - resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" + resolved "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz" integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== deepmerge@^4.2.2: version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== detect-newline@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== diff-sequences@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== diff@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== electron-to-chromium@^1.4.601: version "1.4.614" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz" integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== emittery@^0.13.1: version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emojilib@^2.4.0: version "2.4.0" - resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e" + resolved "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz" integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw== environment@^1.0.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" + resolved "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz" integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== eslint-plugin-prettier@^5.4.1: version "5.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" + resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz" integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== dependencies: prettier-linter-helpers "^1.0.0" @@ -1599,12 +1587,12 @@ eslint-plugin-prettier@^5.4.1: eslint-plugin-unused-imports@^4.1.4: version "4.1.4" - resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" + resolved "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz" integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== eslint-scope@^8.2.0: version "8.2.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz" integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== dependencies: esrecurse "^4.3.0" @@ -1612,17 +1600,17 @@ eslint-scope@^8.2.0: eslint-visitor-keys@^3.3.0: version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint-visitor-keys@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" + resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== eslint@^9.20.1: version "9.20.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" + resolved "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz" integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -1662,7 +1650,7 @@ eslint@^9.20.1: espree@^10.0.1, espree@^10.3.0: version "10.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" + resolved "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz" integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== dependencies: acorn "^8.14.0" @@ -1671,36 +1659,36 @@ espree@^10.0.1, espree@^10.3.0: esprima@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.5.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz" integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== execa@^5.0.0, execa@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" @@ -1715,12 +1703,12 @@ execa@^5.0.0, execa@^5.1.1: exit@^0.1.2: version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== expect@^29.0.0, expect@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== dependencies: "@jest/expect-utils" "^29.7.0" @@ -1731,24 +1719,24 @@ expect@^29.0.0, expect@^29.7.0: fast-check@^3.22.0: version "3.23.2" - resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.23.2.tgz#0129f1eb7e4f500f58e8290edc83c670e4a574a2" + resolved "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz" integrity sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A== dependencies: pure-rand "^6.1.0" fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2: version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.3.2: version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -1759,50 +1747,50 @@ fast-glob@^3.3.2: fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz" integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" fb-watchman@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" fflate@^0.8.2: version "0.8.2" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + resolved "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz" integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== file-entry-cache@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: flat-cache "^4.0.0" fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -1810,7 +1798,7 @@ find-up@^4.0.0, find-up@^4.1.0: find-up@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -1818,7 +1806,7 @@ find-up@^5.0.0: flat-cache@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz" integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" @@ -1826,12 +1814,12 @@ flat-cache@^4.0.0: flatted@^3.2.9: version "3.3.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz" integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2: @@ -1841,51 +1829,51 @@ fsevents@^2.3.2: function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== get-stdin@^8.0.0: version "8.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" + resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz" integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== get-stream@^6.0.0: version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== glob-parent@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" glob@^7.1.3, glob@^7.1.4: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1897,7 +1885,7 @@ glob@^7.1.3, glob@^7.1.4: glob@^8.0.1: version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" + resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: fs.realpath "^1.0.0" @@ -1908,78 +1896,78 @@ glob@^8.0.1: globals@^11.1.0: version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^14.0.0: version "14.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz" integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== graceful-fs@^4.2.9: version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphemer@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== hasown@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz" integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== dependencies: function-bind "^1.1.2" highlight.js@^10.7.1: version "10.7.3" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz" integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== human-signals@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== iconv-lite@^0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" ignore-walk@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776" + resolved "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz" integrity sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw== dependencies: minimatch "^5.0.1" ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -1987,7 +1975,7 @@ import-fresh@^3.2.1: import-local@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" @@ -1995,17 +1983,17 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -2013,71 +2001,71 @@ inflight@^1.0.4: inherits@2, inherits@^2.0.3: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-core-module@^2.13.0: version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: hasown "^2.0.0" is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-generator-fn@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-node-process@^1.2.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" + resolved "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz" integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== is-number@^7.0.0: version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== istanbul-lib-instrument@^5.0.4: version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: "@babel/core" "^7.12.3" @@ -2088,7 +2076,7 @@ istanbul-lib-instrument@^5.0.4: istanbul-lib-instrument@^6.0.0: version "6.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz" integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== dependencies: "@babel/core" "^7.12.3" @@ -2099,7 +2087,7 @@ istanbul-lib-instrument@^6.0.0: istanbul-lib-report@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" @@ -2108,7 +2096,7 @@ istanbul-lib-report@^3.0.0: istanbul-lib-source-maps@^4.0.0: version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: debug "^4.1.1" @@ -2117,7 +2105,7 @@ istanbul-lib-source-maps@^4.0.0: istanbul-reports@^3.1.3: version "3.1.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz" integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== dependencies: html-escaper "^2.0.0" @@ -2125,7 +2113,7 @@ istanbul-reports@^3.1.3: jest-changed-files@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz" integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== dependencies: execa "^5.0.0" @@ -2134,7 +2122,7 @@ jest-changed-files@^29.7.0: jest-circus@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz" integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== dependencies: "@jest/environment" "^29.7.0" @@ -2160,7 +2148,7 @@ jest-circus@^29.7.0: jest-cli@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz" integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== dependencies: "@jest/core" "^29.7.0" @@ -2177,7 +2165,7 @@ jest-cli@^29.7.0: jest-config@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + resolved "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz" integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== dependencies: "@babel/core" "^7.11.6" @@ -2205,7 +2193,7 @@ jest-config@^29.7.0: jest-diff@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz" integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== dependencies: chalk "^4.0.0" @@ -2215,14 +2203,14 @@ jest-diff@^29.7.0: jest-docblock@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz" integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== dependencies: detect-newline "^3.0.0" jest-each@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + resolved "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz" integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== dependencies: "@jest/types" "^29.6.3" @@ -2233,7 +2221,7 @@ jest-each@^29.7.0: jest-environment-node@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== dependencies: "@jest/environment" "^29.7.0" @@ -2245,12 +2233,12 @@ jest-environment-node@^29.7.0: jest-get-type@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== jest-haste-map@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz" integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== dependencies: "@jest/types" "^29.6.3" @@ -2269,7 +2257,7 @@ jest-haste-map@^29.7.0: jest-leak-detector@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz" integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== dependencies: jest-get-type "^29.6.3" @@ -2277,7 +2265,7 @@ jest-leak-detector@^29.7.0: jest-matcher-utils@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz" integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== dependencies: chalk "^4.0.0" @@ -2287,7 +2275,7 @@ jest-matcher-utils@^29.7.0: jest-message-util@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== dependencies: "@babel/code-frame" "^7.12.13" @@ -2302,7 +2290,7 @@ jest-message-util@^29.7.0: jest-mock@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== dependencies: "@jest/types" "^29.6.3" @@ -2311,17 +2299,17 @@ jest-mock@^29.7.0: jest-pnp-resolver@^1.2.2: version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== jest-regex-util@^29.6.3: version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz" integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== jest-resolve-dependencies@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz" integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== dependencies: jest-regex-util "^29.6.3" @@ -2329,7 +2317,7 @@ jest-resolve-dependencies@^29.7.0: jest-resolve@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== dependencies: chalk "^4.0.0" @@ -2344,7 +2332,7 @@ jest-resolve@^29.7.0: jest-runner@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz" integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== dependencies: "@jest/console" "^29.7.0" @@ -2371,7 +2359,7 @@ jest-runner@^29.7.0: jest-runtime@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz" integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== dependencies: "@jest/environment" "^29.7.0" @@ -2399,7 +2387,7 @@ jest-runtime@^29.7.0: jest-snapshot@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz" integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== dependencies: "@babel/core" "^7.11.6" @@ -2425,7 +2413,7 @@ jest-snapshot@^29.7.0: jest-util@^29.0.0, jest-util@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== dependencies: "@jest/types" "^29.6.3" @@ -2437,7 +2425,7 @@ jest-util@^29.0.0, jest-util@^29.7.0: jest-validate@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== dependencies: "@jest/types" "^29.6.3" @@ -2449,7 +2437,7 @@ jest-validate@^29.7.0: jest-watcher@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz" integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== dependencies: "@jest/test-result" "^29.7.0" @@ -2463,7 +2451,7 @@ jest-watcher@^29.7.0: jest-worker@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== dependencies: "@types/node" "*" @@ -2473,7 +2461,7 @@ jest-worker@^29.7.0: jest@^29.4.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + resolved "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz" integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: "@jest/core" "^29.7.0" @@ -2483,12 +2471,12 @@ jest@^29.4.0: js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" @@ -2496,71 +2484,79 @@ js-yaml@^3.13.1: js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== json-buffer@3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-schema-to-ts@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz#81f3acaf5a34736492f6f5f51870ef9ece1ca853" + integrity sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g== + dependencies: + "@babel/runtime" "^7.18.3" + ts-algebra "^2.0.0" + json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stringify-safe@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== json5@^2.2.2, json5@^2.2.3: version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonc-parser@^3.2.0: version "3.2.1" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz" integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== keyv@^4.5.4: version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" kleur@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== leven@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== levn@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" @@ -2568,74 +2564,74 @@ levn@^0.4.1: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash.memoize@4.x: version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lru-cache@^10.4.3: version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" make-dir@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== dependencies: semver "^7.5.3" make-error@1.x, make-error@^1.1.1: version "1.3.6" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== makeerror@1.0.12: version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: tmpl "1.0.5" marked-terminal@^7.1.0: version "7.2.1" - resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-7.2.1.tgz#9c1ae073a245a03c6a13e3eeac6f586f29856068" + resolved "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.2.1.tgz" integrity sha512-rQ1MoMFXZICWNsKMiiHwP/Z+92PLKskTPXj+e7uwXmuMPkNn7iTqC+IvDekVm1MPeC9wYQeLxeFaOvudRR/XbQ== dependencies: ansi-escapes "^7.0.0" @@ -2648,22 +2644,22 @@ marked-terminal@^7.1.0: marked@^9.1.2: version "9.1.6" - resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695" + resolved "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz" integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q== merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.3.0: version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" @@ -2671,53 +2667,53 @@ micromatch@^4.0.4: mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimatch@^5.0.1: version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" minimatch@^9.0.4: version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" minimist@^1.2.6: version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== mri@^1.1.0: version "1.2.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@^2.1.3: version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== mz@^2.4.0: version "2.7.0" - resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz" integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" @@ -2726,12 +2722,12 @@ mz@^2.4.0: natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== nock@^14.0.10: version "14.0.10" - resolved "https://registry.yarnpkg.com/nock/-/nock-14.0.10.tgz#d6f4e73e1c6b4b7aa19d852176e68940e15cd19d" + resolved "https://registry.npmjs.org/nock/-/nock-14.0.10.tgz" integrity sha512-Q7HjkpyPeLa0ZVZC5qpxBt5EyLczFJ91MEewQiIi9taWuA0KB/MDJlUWtON+7dGouVdADTQsf9RA7TZk6D8VMw== dependencies: "@mswjs/interceptors" "^0.39.5" @@ -2740,7 +2736,7 @@ nock@^14.0.10: node-emoji@^2.1.3: version "2.1.3" - resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06" + resolved "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz" integrity sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA== dependencies: "@sindresorhus/is" "^4.6.0" @@ -2750,34 +2746,34 @@ node-emoji@^2.1.3: node-int64@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-releases@^2.0.14: version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== normalize-path@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== npm-bundled@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-2.0.1.tgz#94113f7eb342cd7a67de1e789f896b04d2c600f4" + resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz" integrity sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw== dependencies: npm-normalize-package-bin "^2.0.0" npm-normalize-package-bin@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff" + resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz" integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ== npm-packlist@^5.1.3: version "5.1.3" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.3.tgz#69d253e6fd664b9058b85005905012e00e69274b" + resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz" integrity sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg== dependencies: glob "^8.0.1" @@ -2787,33 +2783,33 @@ npm-packlist@^5.1.3: npm-run-path@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" object-assign@^4.0.1: version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" onetime@^5.1.2: version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" optionator@^0.9.3: version "0.9.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz" integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: "@aashutoshrathi/word-wrap" "^1.2.3" @@ -2825,66 +2821,66 @@ optionator@^0.9.3: outvariant@^1.4.0, outvariant@^1.4.3: version "1.4.3" - resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" + resolved "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz" integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== p-all@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" + resolved "https://registry.npmjs.org/p-all/-/p-all-3.0.0.tgz" integrity sha512-qUZbvbBFVXm6uJ7U/WDiO0fv6waBMbjlCm4E66oZdRR+egswICarIdHyVSZZHudH8T5SF8x/JG0q0duFzPnlBw== dependencies: p-map "^4.0.0" p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" p-map@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-json@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -2894,88 +2890,83 @@ parse-json@^5.2.0: parse5-htmlparser2-tree-adapter@^6.0.0: version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + resolved "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== dependencies: parse5 "^6.0.1" parse5@^5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + resolved "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== parse5@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picocolors@^1.1.1: +picocolors@^1.0.0, picocolors@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pirates@^4.0.4: version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== dependencies: fast-diff "^1.1.2" prettier@^3.0.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" + resolved "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz" integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== dependencies: "@jest/schemas" "^29.6.3" @@ -2984,7 +2975,7 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: prompts@^2.0.1: version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== dependencies: kleur "^3.0.3" @@ -2992,12 +2983,12 @@ prompts@^2.0.1: propagate@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + resolved "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz" integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== publint@^0.2.12: version "0.2.12" - resolved "https://registry.yarnpkg.com/publint/-/publint-0.2.12.tgz#d25cd6bd243d5bdd640344ecdddb3eeafdcc4059" + resolved "https://registry.npmjs.org/publint/-/publint-0.2.12.tgz" integrity sha512-YNeUtCVeM4j9nDiTT2OPczmlyzOkIXNtdDZnSuajAxS/nZ6j3t7Vs9SUB4euQNddiltIwu7Tdd3s+hr08fAsMw== dependencies: npm-packlist "^5.1.3" @@ -3006,32 +2997,27 @@ publint@^0.2.12: punycode@^2.1.0: version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -pure-rand@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" - integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== - -pure-rand@^6.1.0: +pure-rand@^6.0.0, pure-rand@^6.1.0: version "6.1.0" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== react-is@^18.0.0: version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== readable-stream@^3.4.0: version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" @@ -3040,34 +3026,34 @@ readable-stream@^3.4.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve.exports@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== resolve@^1.20.0: version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: is-core-module "^2.13.0" @@ -3076,92 +3062,92 @@ resolve@^1.20.0: reusify@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" sade@^1.8.1: version "1.8.1" - resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + resolved "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz" integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== dependencies: mri "^1.1.0" safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== semver@^6.3.0, semver@^6.3.1: version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.5.3: version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" semver@^7.5.4: version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== semver@^7.6.0: version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== sisteransi@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== skin-tone@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/skin-tone/-/skin-tone-2.0.0.tgz#4e3933ab45c0d4f4f781745d64b9f4c208e41237" + resolved "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz" integrity sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA== dependencies: unicode-emoji-modifier-base "^1.0.0" slash@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== source-map-support@0.5.13: version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== dependencies: buffer-from "^1.0.0" @@ -3169,29 +3155,29 @@ source-map-support@0.5.13: source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stack-utils@^2.0.3: version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" strict-event-emitter@^0.5.1: version "0.5.1" - resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" + resolved "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz" integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== string-length@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== dependencies: char-regex "^1.0.2" @@ -3199,14 +3185,14 @@ string-length@^4.0.1: string-to-stream@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/string-to-stream/-/string-to-stream-3.0.1.tgz#480e6fb4d5476d31cb2221f75307a5dcb6638a42" + resolved "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz" integrity sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg== dependencies: readable-stream "^3.4.0" string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -3215,67 +3201,67 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== superstruct@^1.0.4: version "1.0.4" - resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" + resolved "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-color@^8.0.0: version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-hyperlinks@^3.1.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz#b56150ff0173baacc15f21956450b61f2b18d3ac" + resolved "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz" integrity sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A== dependencies: has-flag "^4.0.0" @@ -3283,19 +3269,19 @@ supports-hyperlinks@^3.1.0: supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== synckit@^0.11.7: version "0.11.8" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" + resolved "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz" integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== dependencies: "@pkgr/core" "^0.2.4" test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" @@ -3304,43 +3290,48 @@ test-exclude@^6.0.0: thenify-all@^1.0.0: version "1.6.0" - resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.1" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz" integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== dependencies: any-promise "^1.0.0" tmpl@1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" +ts-algebra@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz" + integrity sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw== + ts-api-utils@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" + resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz" integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== ts-jest@^29.1.0: version "29.1.1" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" + resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz" integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== dependencies: bs-logger "0.x" @@ -3354,7 +3345,7 @@ ts-jest@^29.1.0: ts-node@^10.5.0: version "10.7.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz" integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== dependencies: "@cspotcode/source-map-support" "0.7.0" @@ -3373,7 +3364,8 @@ ts-node@^10.5.0: "tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz" + integrity sha512-tWyCXnx0WqCkVlo5s+4KMj7HC0/0YrCZY0PustUwX9F2lNwd8Kp07q/Q56uGvV9q80XaSDrhy0YqBmrX5TDNpQ== dependencies: debug "^4.3.7" fast-glob "^3.3.2" @@ -3388,7 +3380,7 @@ ts-node@^10.5.0: tsconfig-paths@^4.0.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== dependencies: json5 "^2.2.2" @@ -3397,29 +3389,29 @@ tsconfig-paths@^4.0.0: tslib@^2.8.1: version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-detect@4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== typescript-eslint@8.31.1: version "8.31.1" - resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.31.1.tgz#b77ab1e48ced2daab9225ff94bab54391a4af69b" + resolved "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.1.tgz" integrity sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA== dependencies: "@typescript-eslint/eslint-plugin" "8.31.1" @@ -3428,32 +3420,27 @@ typescript-eslint@8.31.1: typescript@5.6.1-rc: version "5.6.1-rc" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.1-rc.tgz#d5e4d7d8170174fed607b74cc32aba3d77018e02" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.6.1-rc.tgz" integrity sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ== typescript@5.8.3: version "5.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz" integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== -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== - undici-types@~6.21.0: version "6.21.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz" integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== unicode-emoji-modifier-base@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" + resolved "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz" integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== update-browserslist-db@^1.0.13: version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz" integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== dependencies: escalade "^3.1.1" @@ -3461,24 +3448,24 @@ update-browserslist-db@^1.0.13: uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" util-deprecate@^1.0.1: version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== v8-compile-cache-lib@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz" integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== v8-to-istanbul@^9.0.1: version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz" integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" @@ -3487,26 +3474,26 @@ v8-to-istanbul@^9.0.1: validate-npm-package-name@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" + resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz" integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== walker@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: makeerror "1.0.12" which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.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" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -3515,12 +3502,12 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^4.0.2: version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== dependencies: imurmurhash "^0.1.4" @@ -3528,37 +3515,37 @@ write-file-atomic@^4.0.2: ws@^8.18.0: version "8.18.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^3.0.2: version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yargs-parser@^20.2.2: version "20.2.9" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^16.0.0: version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -3571,7 +3558,7 @@ yargs@^16.0.0: yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -3584,15 +3571,15 @@ yargs@^17.3.1, yargs@^17.7.2: yn@3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== "zod@^3.25 || ^4.0": version "4.1.11" - resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.11.tgz#4aab62f76cfd45e6c6166519ba31b2ea019f75f5" + resolved "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz" integrity sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg== From 1093bd05eaf36165eaca34a347ffeeba889be038 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 10:32:34 -0500 Subject: [PATCH 13/43] throw when n>1 --- src/lib/beta/BetaToolRunner.ts | 5 +++++ tests/lib/tools/ToolRunner.test.ts | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 85f1df2ba..13b8f42cd 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -72,6 +72,11 @@ export class BetaToolRunner { params: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions, ) { + params.n ??= 1; + if (params && params.n > 1) { + throw new Error('BetaToolRunner does not support n > 1'); + } + this.#state = { params: { // You can't clone the entire params since there are functions as handlers. diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index 0bf1ddf0c..cb650682c 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -1,8 +1,4 @@ import OpenAI from 'openai'; -// import { BetaMessage, BetaContentBlock, BetaToolResultBlockParam } from 'openai/sdk/resources/beta'; -// import { BetaRunnableTool } from 'openai/sdk/lib/tools/BetaRunnableTool'; -// import { BetaRawMessageStreamEvent } from 'openai/sdk/resources/beta/messages'; -// import { Fetch } from 'openai/sdk/internal/builtin-types'; import { mockFetch } from '../../utils/mock-fetch'; import { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; import { @@ -432,6 +428,16 @@ describe('ToolRunner', () => { ); }); + it('throws when constructed with n>1', async () => { + expect(() => { + setupTest({ n: 999 }); + }).toThrow('BetaToolRunner does not support n > 1'); + + expect(() => { + setupTest({ n: null }); + }).not.toThrow(); + }); + describe('iterator.next()', () => { it('yields CompletionMessage', async () => { const { runner, handleAssistantMessage } = setupTest(); From 844c5a449a1e70b1c85b7a42c35bc71308b18bbe Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:00:06 -0500 Subject: [PATCH 14/43] update another test --- tests/lib/tools/ToolRunner.test.ts | 203 +++++++++++++++++++++++++++-- 1 file changed, 195 insertions(+), 8 deletions(-) diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index cb650682c..ae18b8164 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -472,9 +472,132 @@ describe('ToolRunner', () => { for await (const event of stream) { events.push(event); } - // Verify we get the expected number of events (with chunked JSON, we'll get more deltas), but we - // should get at least 6 including - expect(events.length).toBeGreaterThanOrEqual(6); + + // 1. Initial chunk with role only (no content, no tool_calls) + expect(events[0]).toMatchObject({ + choices: [ + { + delta: { + content: null, + refusal: null, + role: 'assistant', + }, + finish_reason: null, + index: 0, + }, + ], + object: 'chat.completion.chunk', + }); + + // 2. Tool call chunk with function name + expect(events[1]).toMatchObject({ + choices: [ + { + delta: { + tool_calls: [ + { + index: 0, + id: 'tool_1', + type: 'function', + function: { + name: 'getWeather', + }, + }, + ], + content: null, + refusal: null, + }, + finish_reason: null, + }, + ], + object: 'chat.completion.chunk', + }); + + // 3-5. Argument chunks (3 chunks for the JSON string) + expect(events[2]).toMatchObject({ + choices: [ + { + delta: { + tool_calls: [ + { + index: 0, + function: { + arguments: expect.any(String), + }, + }, + ], + content: null, + refusal: null, + }, + finish_reason: null, + }, + ], + object: 'chat.completion.chunk', + }); + + expect(events[3]).toMatchObject({ + choices: [ + { + delta: { + tool_calls: [ + { + index: 0, + function: { + arguments: expect.any(String), + }, + }, + ], + content: null, + refusal: null, + }, + finish_reason: null, + }, + ], + object: 'chat.completion.chunk', + }); + + expect(events[4]).toMatchObject({ + choices: [ + { + delta: { + tool_calls: [ + { + index: 0, + function: { + arguments: expect.any(String), + }, + }, + ], + content: null, + refusal: null, + }, + finish_reason: null, + }, + ], + object: 'chat.completion.chunk', + }); + + // 6. Final chunk with finish_reason + expect(events[5]).toMatchObject({ + choices: [ + { + delta: { + content: null, + role: 'assistant', + refusal: null, + }, + finish_reason: 'tool_calls', + }, + ], + object: 'chat.completion.chunk', + usage: { + prompt_tokens: 10, + completion_tokens: 20, + total_tokens: 30, + }, + }); + + expect(events.length).toBe(6); }); // Second iteration: assistant provides final response @@ -487,11 +610,75 @@ describe('ToolRunner', () => { for await (const event of stream2) { events2.push(event); } + // Assert the expected structure of events2 + expect(events2).toHaveLength(4); - // With chunked text, we'll get multiple text_delta events - // expect(events2.length).toBeGreaterThanOrEqual(6); - // const textDeltas = events2.filter((e) => e.type === 'content_block_delta'); - // expect(textDeltas.length).toBeGreaterThanOrEqual(1); + // 1. Initial chunk with role only + expect(events2[0]).toMatchObject({ + choices: [ + { + delta: { + content: null, + refusal: null, + role: 'assistant', + }, + finish_reason: null, + index: 0, + }, + ], + object: 'chat.completion.chunk', + }); + + // 2. First text content delta + expect(events2[1]).toMatchObject({ + choices: [ + { + delta: { + content: 'Some text ', + refusal: null, + }, + index: 0, + finish_reason: null, + }, + ], + object: 'chat.completion.chunk', + }); + + // 3. Second text content delta + expect(events2[2]).toMatchObject({ + choices: [ + { + delta: { + content: 'content', + refusal: null, + }, + index: 0, + finish_reason: null, + }, + ], + object: 'chat.completion.chunk', + }); + + // 4. Final chunk with finish_reason and usage + expect(events2[3]).toMatchObject({ + choices: [ + { + delta: { + content: null, + role: 'assistant', + refusal: null, + }, + index: 0, + finish_reason: 'stop', + }, + ], + object: 'chat.completion.chunk', + usage: { + prompt_tokens: 10, + completion_tokens: 20, + total_tokens: 30, + }, + }); await expectDone(iterator); }); @@ -692,7 +879,7 @@ describe('ToolRunner', () => { it('respects max_iterations parameter', async () => { const { runner, handleAssistantMessage } = setupTest({ - messages: [{ role: 'user', content: 'Use tools repeatedly' }], + messages: [{ role: 'user', content: 'Use tools repeatedly, one at a time' }], max_iterations: 2, // Limit to 2 iterations }); From 49bbff65383e28687610d7aeb59f3ba3e2e890b8 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:14:52 -0500 Subject: [PATCH 15/43] make tool runner beta only --- examples/tool-helpers-advanced-streaming.ts | 2 +- examples/tool-helpers-advanced.ts | 2 +- examples/tool-helpers-json-schema.ts | 2 +- src/resources/beta/beta.ts | 4 +-- src/resources/beta/chat.ts | 26 +++++++++++++++++++ src/resources/chat/completions/completions.ts | 20 +------------- 6 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 src/resources/beta/chat.ts diff --git a/examples/tool-helpers-advanced-streaming.ts b/examples/tool-helpers-advanced-streaming.ts index c110bb43d..aa28afd65 100644 --- a/examples/tool-helpers-advanced-streaming.ts +++ b/examples/tool-helpers-advanced-streaming.ts @@ -7,7 +7,7 @@ import { z } from 'zod'; const client = new OpenAI(); async function main() { - const runner = client.chat.completions.toolRunner({ + const runner = client.beta.chat.completions.toolRunner({ messages: [ { role: 'user', diff --git a/examples/tool-helpers-advanced.ts b/examples/tool-helpers-advanced.ts index 88b6bafff..eac810305 100644 --- a/examples/tool-helpers-advanced.ts +++ b/examples/tool-helpers-advanced.ts @@ -7,7 +7,7 @@ import { z } from 'zod'; const client = new OpenAI(); async function main() { - const message = await client.chat.completions.toolRunner({ + const message = await client.beta.chat.completions.toolRunner({ messages: [ { role: 'user', diff --git a/examples/tool-helpers-json-schema.ts b/examples/tool-helpers-json-schema.ts index 81c8d75ec..5c602830c 100644 --- a/examples/tool-helpers-json-schema.ts +++ b/examples/tool-helpers-json-schema.ts @@ -6,7 +6,7 @@ import { betaTool } from 'openai/helpers/beta/json-schema'; const client = new OpenAI(); async function main() { - const message = await client.chat.completions.toolRunner({ + const message = await client.beta.chat.completions.toolRunner({ messages: [ { role: 'user', diff --git a/src/resources/beta/beta.ts b/src/resources/beta/beta.ts index 6014b961b..c7dbb7df5 100644 --- a/src/resources/beta/beta.ts +++ b/src/resources/beta/beta.ts @@ -74,7 +74,7 @@ import { TranscriptionSessionUpdatedEvent, } from './realtime/realtime'; import * as ChatKitAPI from './chatkit/chatkit'; -import * as ChatAPI from '../chat/chat'; +import { BetaChat as BetaChatAPI } from './chat'; import { ChatKit, ChatKitWorkflow } from './chatkit/chatkit'; import * as ThreadsAPI from './threads/threads'; import { @@ -100,7 +100,7 @@ export class Beta extends APIResource { chatkit: ChatKitAPI.ChatKit = new ChatKitAPI.ChatKit(this._client); assistants: AssistantsAPI.Assistants = new AssistantsAPI.Assistants(this._client); threads: ThreadsAPI.Threads = new ThreadsAPI.Threads(this._client); - chat: ChatAPI.Chat = new ChatAPI.Chat(this._client); + chat: BetaChatAPI = new BetaChatAPI(this._client); } Beta.Realtime = Realtime; diff --git a/src/resources/beta/chat.ts b/src/resources/beta/chat.ts new file mode 100644 index 000000000..86dd680b0 --- /dev/null +++ b/src/resources/beta/chat.ts @@ -0,0 +1,26 @@ +import { APIResource } from '../../resource'; +import { + BetaToolRunner, + type BetaToolRunnerParams, + type BetaToolRunnerRequestOptions, +} from '../../lib/beta/BetaToolRunner'; +import { Chat as ChatResource } from '../../resources'; + +export class BetaCompletions extends ChatResource.Completions { + toolRunner( + body: BetaToolRunnerParams & { stream?: false }, + options?: BetaToolRunnerRequestOptions, + ): BetaToolRunner; + toolRunner( + body: BetaToolRunnerParams & { stream: true }, + options?: BetaToolRunnerRequestOptions, + ): BetaToolRunner; + toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner; + toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner { + return new BetaToolRunner(this._client, body, options); + } +} + +export class BetaChat extends APIResource { + completions: BetaCompletions = new BetaCompletions(this._client); +} diff --git a/src/resources/chat/completions/completions.ts b/src/resources/chat/completions/completions.ts index 7a5207946..31f410562 100644 --- a/src/resources/chat/completions/completions.ts +++ b/src/resources/chat/completions/completions.ts @@ -19,12 +19,7 @@ import { ChatCompletionToolRunnerParams } from '../../../lib/ChatCompletionRunne import { ChatCompletionStreamingToolRunnerParams } from '../../../lib/ChatCompletionStreamingRunner'; import { ChatCompletionStream, type ChatCompletionStreamParams } from '../../../lib/ChatCompletionStream'; import { ExtractParsedContentFromParams, parseChatCompletion, validateInputTools } from '../../../lib/parser'; -import { - BetaToolRunner, - type BetaToolRunnerRequestOptions, - type BetaToolRunnerParams, -} from '../../../lib/beta/BetaToolRunner'; -import type OpenAI from '../../../index'; +import { BetaToolRunner } from '../../../lib/beta/BetaToolRunner'; export class Completions extends APIResource { messages: MessagesAPI.Messages = new MessagesAPI.Messages(this._client); @@ -198,19 +193,6 @@ export class Completions extends APIResource { return ChatCompletionRunner.runTools(this._client, body as ChatCompletionToolRunnerParams, options); } - toolRunner( - body: BetaToolRunnerParams & { stream?: false }, - options?: BetaToolRunnerRequestOptions, - ): BetaToolRunner; - toolRunner( - body: BetaToolRunnerParams & { stream: true }, - options?: BetaToolRunnerRequestOptions, - ): BetaToolRunner; - toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner; - toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner { - return new BetaToolRunner(this._client as OpenAI, body, options); - } - /** * Creates a chat completion stream */ From f730423bcb718fea6975fc12f38985b80f6d04ce Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:16:04 -0500 Subject: [PATCH 16/43] update snapshot --- tests/lib/tools/nockFixtures/ToolRunner.json | 924 ++++++++++--------- 1 file changed, 465 insertions(+), 459 deletions(-) diff --git a/tests/lib/tools/nockFixtures/ToolRunner.json b/tests/lib/tools/nockFixtures/ToolRunner.json index 89c2ea927..e50620c0a 100644 --- a/tests/lib/tools/nockFixtures/ToolRunner.json +++ b/tests/lib/tools/nockFixtures/ToolRunner.json @@ -1,474 +1,480 @@ [ - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "value": { - "type": "string" + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." } - } - } - } - } - ], - "stream": false - }, - "status": 200, - "response": [ - "1b3404201c07ce392f9674370bc94efe64815e55fdd411cb03dfd840a050cf2b7479e5956869eb28b0f43db8dc3fbf2db4986eb607beb7b91f131b3c45c3b28453ca361b41a33e11419d36a7a73dab77eb50ec0144f2676e5e65ec2e7e8e1fddefc93c885f77d12593efbb9b2970a565d898cfd8d0104531f4010924c1fd7c06a2ae29ba600a82baa18d306f8755c72a259ba65356308e4d6de3fc37777f06febea0712f81c05ce4514c406e8b9a329b3a88fb11864b86f5617918038634885adab74df99faaab40f61f28fd3c26ce97adc9dfb5f1f4ba3d1efdc22d859718d30262c122e18b13514847128621b8a00ee45d525796590b2d1a66105dacbf08b1ff0b4feff917c77af13a2daf37f887062fd8999b42d4c4d6dad6b990bc949561d5944eabddac0235295d8ca8c39bd9c2569cd6c7b45bb5fa79d551b2efb54093e6528c0be19ea8608a84204fd7a2376c11ffc39e6f94e12d4f26ca36ccee304696c7db93f6f6e480abe322dc159382d0a2e743a89ba824bfa8a92275b3759cf587d4c57e03504711a7bad0a237f860b941fa7ead48334cc7f60cdfb4d105" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbb91b9d442f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:45 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "332", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=lpPj9JFyqlPPHP_HkoosAVe0qXpd8Sv7nn2TbPz.7XU-1764709005788-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "648", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999974", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_f2c619799e6a49df915d7151b34af812" - }, - "responseIsBinary": false - }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "value": { + "type": "string" + } + } + } + } + } + ], + "n": 1, + "stream": false }, - { - "role": "assistant", - "content": null, - "tool_calls": [ - { - "id": "call_kXFjbYa63Zq8QTBFFenco0Si", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"value\":\"test\"}" - } - } - ], - "refusal": null, - "annotations": [] + "status": 200, + "response": [ + "1b3404201c07ce392f9674370bc94efe64a16ed37e734d47c4f46b02248853a8e715babcf24ab4b4751458fa1e5cee9f9f1fed996e36d6f036f7636283a76818269c52b6d588a0ad3e11418db6ae8ef6eceed37f288f0022f9b3f0cc4f622d2f98957da6dbeaf2e23693e2f7736deb75377ae562146043431445cf0f482009ee670654e57dc3b61dd35416b411e6dd943f44838969da1315e75cb276ce7f737f37f08f218d7b0514e1268fa20b723b7463a7a98ab89f60b8645803967b31604891a8a57dd392fd97ea2a90fd07aa18c5477b76da3abfde9f8bda64d12959b35ef4312d2016ac12be20118574245e18820bea40de153d183b35cfaa6106d1e17f8f102ff7f0f45ef738b6abd76576bdc17f68f08a7f7293879ad8cadbaa1792b74e2ce53716dcb54b55a012a58be17778295bd88af39e31adc5b7e5993f28d90feec0d2e64c8cf3e0b66a608a7820dbb6fc0f2c13ffbd9e2f96e1e548c6cf36cc6e2f469607db13f5f1e4809bf34b7a282605a14cef074f377e49fe50932375b3759cf5c7f4c8e31b401d459cea4299bee083e506e9fb9593e5b8811f39b1eba30b" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a845d712abc8c27-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 16:15:50 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "375", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=23PiD.Xem7RLutUsn3Z8kgcrKzxIJ6umxTQi.bA72wI-1764778550408-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "388", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999974", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_f7524cf93f5a4270a594f5dd1572b544" }, - { - "role": "tool", - "content": "Tool result", - "tool_call_id": "call_kXFjbYa63Zq8QTBFFenco0Si" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "value": { - "type": "string" - } - } - } - } - } - ], - "stream": false + "responseIsBinary": false }, - "status": 200, - "response": [ - "1b6603081c056eacc77324e1504f6156da56b599addfbcc35ad5bc0970c1ac411494fab6820e4b57ffffaf768687561aa1c063f9dbf2da16d174bd53bb15771248c3b284b3989b591b471afd303be6a72f0c558a603bff961cc541ee54e36a48c3a2d77fce75db6b3e5df25b6bb47cf5ec76b030cc534bc3271224a68c7d4774d7b15ccdd734bb1603e5d162216eb245b2adce64cdeb46a7564e20996fa8ea2f019367fe4493186a2a4304ab946f10376336ff0683d4cc794ed3a75d6607f6942046dffb945d0e91f22b6df15dcc0edb8a17819c4831a17e03984507410e00605bc5e4e865f73f9db70e54880bc5571511d61bf9514b3c0ee310d216d86e5ddf576209e2424771e314e18a479e935c609f00aa745b1c2c643fd27429247e6c70dd03884129d8dc24410a04e4f8778fead03ee4023c599d8a16016d47c4dd2acebc81abe78dda328b9dfe155936f9adca2e08dc8f80249d88df7c23ac94a3bf73c11dcf8fa3d4cbfc080e" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbb966db942f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:46 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "453", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=dIQGF8J5UWhZ4SvG6kU7vUjxKahEtpjMKX7lCEQJmWA-1764709006362-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "470", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999969", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_94e15302a82b469cb4d179718e715ba0" - }, - "responseIsBinary": false - }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "count": { - "type": "number" + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with value \"test\", then provide a final response that includes the word 'foo'." + }, + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_A4jx2uIH3pqsuUCQUIkoFDjL", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"value\":\"test\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + { + "role": "tool", + "content": "Tool result", + "tool_call_id": "call_A4jx2uIH3pqsuUCQUIkoFDjL" } - } - } - } - } - ], - "stream": false - }, - "status": 200, - "response": [ - "1b1205601c0776d356336ef452185b7fa2989c27747bf5885a1bdb4a7d19d3c8f1223edcdf538745e18f7b779fe3d0c2147abb318777f19e1e25169695684a89628b6ec24c3f62d29e6ccf6e287400c8e3d7ecb448483ddc84eba0eb95ac3ed07c39163efadc6ea7eac1daacd6f09083ca36f6f311182f5a5e03ac2c0932a3328cf4260bf1d4ef170d29e46493d64946210ffc96ee773e5d076e80bc76b20c01121f7280aa4899e90190f53318abfd95a4c6c731581f418cae6996e7fa6d58a090f217509905c754284ec38b255ffaa3fd32bb74b3bdc9c33c585678d5e44d233084f9318ec4d42233966e108db4a75d2dc94858fade2ae0e02df097ff88cfbf8dc3f7f16f81df6a617c5905523c49fc8fa46d4b2be2c7fc7af19ab3757d132dffd5d0779a5101635d47e76b5ba41e2bc9fda2caad9a37dce01ac691c099a8a54896b00d97b5e51aafb8b5d2a2c1716ca00624e5b456338d61dd8240dd3f86b8c7b21c212f82bd3d1ef250a357c4a198ec241ab9c6316cf87473e615cefedf1c66fed7303ad84570ee132553e96427541e59945d2f23da3036a15b0130471096c7bc08ee9d888652aadbb705ba0aabbabcc02b16f401" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbb99e86742f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:47 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "1458", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=qi330.nZqpWAjkxgfpHpx2xbkc2UcZcgIVqzaBpJOJc-1764709007921-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "1470", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999973", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_5d9e0413b7b942aeb8212d70c86dc374" - }, - "responseIsBinary": false - }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" - }, - { - "role": "assistant", - "content": null, - "tool_calls": [ - { - "id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"count\": 1}" - } - }, - { - "id": "call_3SAikZPh6kJlgz6ASqbj3I3Q", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"count\": 2}" - } - } - ], - "refusal": null, - "annotations": [] + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "value": { + "type": "string" + } + } + } + } + } + ], + "n": 1, + "stream": false }, - { - "role": "tool", - "content": "Called with 1", - "tool_call_id": "call_8LhWm4pXGZb7ZEHUOnZvLUa3" + "status": 200, + "response": [ + "1b8003209c0576b33291acec5a442b1f61a0ca79859aaa9fe8d9e29cca471707247fc59c31b7028bce9c38f1fbbf6fe7f3a795120a3c96eebc99d61d344cd7fb6bb7bc1d300dcb124e616cda093da63ef2d3a365212420f9b7a06a4bbaccf2c698c760b82dae61f47a9e2e52f3fb5325f7cf8b07a239d114d217487032d49cef90d23434d3b4745df462476493493b52ada1341d5261cdab46affcf7461fec328f95dc9d8ffb82ec5457f4217928810d4c28e07e028aaba3513fafe6e85620ee44c5a902df19077b0d21f90145f8cfa5aaf34cce2486cf0bc7b86998b9fa0b0103af04b5588cb01617d7ae6dcc8d6f954dd2f68d3fa8ae46e92a863faf0c21b4039459e8c9f1e43d53b57d53b523f2067a762da338083c124fa42da18d85ce099da4350c4b0c4625b6d4423969e484292ce6acbeda429b6aefdc7e655627238b19b96a78ac6547a764ea871ee554f0677fcaa0318e59d46361c72411771cabe1a7e1087521eb77dca261d9be175a91ed0103" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a845d761f1c8c27-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 16:15:51 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "596", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=DxyeRhO5K1.8vDJnFHChY4psCYa11f1v643RPYuvmss-1764778551422-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "617", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999969", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_b8080ce1b79341bd940565c356af3ea5" }, - { - "role": "tool", - "content": "Called with 2", - "tool_call_id": "call_3SAikZPh6kJlgz6ASqbj3I3Q" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "count": { - "type": "number" - } - } - } - } - } - ], - "stream": false + "responseIsBinary": false }, - "status": 200, - "response": [ - "1b4903201c056eacc77324e150cf1165c4dc52dd7d9e6945bdd9c404681085abbeada0c3d275eae63d4771420b30965fedc18145d15ab6388134cdb4053d8b9111aef1af2f044207811d988d9d1609350f6fe17d71de620ce65e789b66c7eba3f5db6cbd6f8e021602262a84ad1f904030a89c6f84536451613596558f5847b428fb4543893955a619c5aad7967ca4f50ff22707ee8b09bbe198b0e493d48a10e1d1358a0d92a0c67d87c1a9d1684b5ec9815aa9c1bdb56b6d3ffdc0d37881a3a7fff48f35139cf92d582b665873fb7bf7afebab24f78b2ab76a6a0ba569e979040c645a086b1ec47b6d5b333d149b222d1a3dffa535c209e20a516823280b9c361dd0954ab2b4f5a4687bd544dabbceb91d029cf26d18d1bd5fa1b1ec89f137c3cc3fb7614a95d87ad36c1bddc1a4df5e244b7534f3a7a550d79bd0ad1034170c27c562eb5f6b836b106155bd42771d59141cf49226c101" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbba3983a42f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:48 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "570", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=BUCKnZnfZHCGps3vl2nGYAx9wF.sgTuV.Mr9F4AhkTk-1764709008586-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "585", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999963", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_7d1925a5797891a7b7bb58f383b71d92" - }, - "responseIsBinary": false - }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "input": { - "type": "string" + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" } - } - } - } - } - ], - "stream": false - }, - "status": 200, - "response": [ - "1b3404201c07ce392f9674370bc94efe64819ed37e73c4b9103ead4353a8e715babcf24ab4b4751458fafefce5ee385b6831f4e66f0f3c6f73372636788a866509a7946d3522d8a53e11418db6ae8ef6ecee5d3b64bf0122f9b3971f796cc75edb9b57642741a771627d3fdf4ffaf96fa0652b63696343535445cf0f48600919e73310754dd10553108c9d6cc4b6fd8b325609d9349db282716e6abbe4bfbd7b19f8c782e6bd04027353663101b92d4a426fe920ee4718ae19d687e55e0c19d2206a99b1f364ffa57115cafe0365b3774739471d63775ad6ddbc7614d9eeb83b13d34262e1aae10b123190998917c6e0a23a92774959187addb39a30a3e8a2bd22e8ce159edef315c776f1baccae37e40f0d565a889b3cd4a4dedadeb990bce485bf28099fa976b30ad4a474b1fc0e6f668b58715a1ed36ed1e6f85146c9be97024d6c9918e7c14ba24229e2814abaea7f608bf8eff57ca30c6fbd65fc6ca3ecf6626c79b03d511fcf0eb8da0e7e87c1b420b4e8fde019c62f291f6a2acbb8397792f58794d99f04a08e12ce75a1455ff0a17243f4fd1ad1c710cd8facc8c6135d" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbba86c8b42f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:49 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "985", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=oJb88Mguy0KPy3QsA56AonUav8eXZp4Vndi.eTdWPoE-1764709009776-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "1002", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999976", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_dc3243bab67944a1b586d7a40f600776" - }, - "responseIsBinary": false - }, - { - "scope": "https://api.openai.com:443", - "method": "POST", - "path": "/v1/chat/completions", - "body": { - "model": "gpt-4o", - "max_tokens": 1000, - "messages": [ - { - "role": "user", - "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "count": { + "type": "number" + } + } + } + } + } + ], + "n": 1, + "stream": false }, - { - "role": "assistant", - "content": null, - "tool_calls": [ - { - "id": "call_tMdC4ZpC8UYPyDuyj43iCkU9", - "type": "function", - "function": { - "name": "test_tool", - "arguments": "{\"input\":\"test\"}" - } - } - ], - "refusal": null, - "annotations": [] + "status": 200, + "response": [ + "1b1205201c0776d356336ef452185b7fa24acf5f68b2ea256a6e49af69cf5c1d343ec4940f20755814feff7bf7e338b43085ce9ded01be0675ee6b2cdad826fb91a6141066d3869a74f1b118b387475b80039f767eff681d0310c9af45fbd3ceceac374765aecdc1bdbe3c5dd68c05224d44463fc9ad3f828f4c948e66010924c1f37c0688925c292d0439514768bdcbd3cde6473b4d6bb6a77f53f2e4fc0ff44f0efed524bb5b8067dd642baa40ae41b1811934ee7b302e195680e516038624915a3a37ee76f02aae02d95fc0763eb5bb7cf8592ffabdd32adedd9adb0bb9ad77702f20161c12be59220aa9251686e04277206f02d5d4af1e1a66106d7ea751383175fde13ff1cdddb87c5be99b7e778ad9866eec4f85fdf298ff841e9323521d97b788a9b6cd176afeb786d136870326eff073ece5abe776c7e52a21765d7ba72aaf29ac059ecba654bab01687dd099b6e91f3cdd30d2b198cdc94dac2364a27838738c7fc37d03b42a835621ab3db3a3d59fd4ac7326e2e61edb218b6dd5368d1e1c90357af0fcb4b312977697cfa99695c497e0d5558eae7e0b8a64de36d9d5c00784a204e552f8def27c2628acc9d3861124bce62f11e23a005" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a845d7c7ba58c27-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 16:15:52 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "760", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=fW433MHslfoC7JTSFlm4_zUnCx_1akGUNhJDEcL4e_c-1764778552600-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "783", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999973", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_8b967c6196c74f4885ff26753d969711" }, - { - "role": "tool", - "content": "Tool result", - "tool_call_id": "call_tMdC4ZpC8UYPyDuyj43iCkU9" - } - ], - "tools": [ - { - "type": "function", - "function": { - "name": "test_tool", - "description": "A test tool", - "parameters": { - "type": "object", - "properties": { - "input": { - "type": "string" + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with count 1, then use it again with count 2, then say '231' in the final message" + }, + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_RFAlrz4q8fVUphdltPkr1til", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"count\": 1}" + } + }, + { + "id": "call_BySHDO8OmpGmBILLU36Y1LZJ", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"count\": 2}" + } + } + ], + "refusal": null, + "annotations": [] + }, + { + "role": "tool", + "content": "Called with 1", + "tool_call_id": "call_RFAlrz4q8fVUphdltPkr1til" + }, + { + "role": "tool", + "content": "Called with 2", + "tool_call_id": "call_BySHDO8OmpGmBILLU36Y1LZJ" } - } - } - } - } - ], - "stream": false + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "count": { + "type": "number" + } + } + } + } + } + ], + "n": 1, + "stream": false + }, + "status": 200, + "response": [ + "1b2503001c07762c33326c3cb8f9269f7e5da9fe7979c57850bb062de40651e8ea9b3a2c0a5337efb9cd890618cb37c6e0c09ea2b52c9d246191f6d0cd4e26f4abbe2d21885c0055fee664654a1fa2b8d0c6267f5da5ea7c571ec56eb8bd5e8d95e483dae010f0a8a46c7c4182042223fa06bcaa48aaaac9b2308b440a151a942d2d15b49f6634a7ed2c65960300c83f99d82526188779c25157653652004408415da4b90bc56f3080ccb5d0ef04915fe4fff863ac54b4eb46d5d0884897bdc2dd287994164159177693dc82e359869500037614a21656e68fe375c78487b22bb2b235ac9bdb005e9416907103c2161ad1265a0909a5fd48dbd0785364266cda76d7b67c457b6ede9468ef2668e8f325e66f4679b0366f2a2e601b11b1c9740b547e35112f55d0d826db79d56823af06881c2280e409b6f1ce1ad1c104b0b25f1a9eab48a20b8fe8327a" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a845d8378c38c27-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 16:15:53 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "346", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=1yYWcIHwMGbk77yjyEEnd1UAcxqAb8lTI6P7da_g0XE-1764778553298-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "361", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999963", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_88771ad4f2e7420fb19f3172cfa904a8" + }, + "responseIsBinary": false }, - "status": 200, - "response": [ - "1b2303201c076eac66e4a0959313a8725ea1a6ea277ab6b4add4974f1cc86fd1930ef7d4615198ba79cf6dce3496ff6f4f0ea4eb7c2d4b274918269c8a6e88495279076f8f56a54090e46f4937b6f4503daa57b2cc7be44517af39c5f2f1be5f57a10e8b27603488f2858d0f4810cf909e53044acf99260f84086afc8e282b17e34acd40cd34a5c29f9bae97ec1f641fecf84723dc308e05d929a148c079256d1edad801b96fe0e3126854ef949683f41b7f5cd462b56e640d81e0d7b22e71f6228fdaa118e7215eae36b33b139504e8a0460154c2cc38c0eb0d83db58e5ddb8a272a37b86be2d1631dc386ea90c6b44f332ca6bdfcf427137f93252682b3da74d2e56e6e631f1c5bb5f67e8ed45e437abbe189bc764fdb7d01d3621b7ce94c22512a4b04c4c52f22aae553603c16de0e3a2195818600db62e74d6773e62e6cb20d346fb313400" - ], - "rawHeaders": { - "access-control-expose-headers": "X-Request-ID", - "alt-svc": "h3=\":443\"; ma=86400", - "cf-cache-status": "DYNAMIC", - "cf-ray": "9a7dbbaf5bd142f8-EWR", - "connection": "keep-alive", - "content-encoding": "br", - "content-type": "application/json", - "date": "Tue, 02 Dec 2025 20:56:50 GMT", - "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "422", - "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", - "openai-version": "2020-10-01", - "server": "cloudflare", - "set-cookie": "_cfuvid=cePexYFkijPVWrWqH3vLF2RIg.1dy1YjD_.Dp8_n7Nk-1764709010314-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", - "strict-transport-security": "max-age=31536000; includeSubDomains; preload", - "transfer-encoding": "chunked", - "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "435", - "x-openai-proxy-wasm": "v0.1", - "x-ratelimit-limit-requests": "10000", - "x-ratelimit-limit-tokens": "30000000", - "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999971", - "x-ratelimit-reset-requests": "6ms", - "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_4e047e9ec0344280be4d034850f217b5" + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "input": { + "type": "string" + } + } + } + } + } + ], + "n": 1, + "stream": false + }, + "status": 200, + "response": [ + "1b3404201c07ce392f9674370bc94efe64d1b6529f8c69864f6e8bf91dbc18857a5ea1cb2baf444b5b4781a5efcf5fee8eb38516436ffef6c0f33677636283a7685896704ad95623825dea1311d468ebea68cfeedefd87ca0420923f8b5bde885e5931f73b5317e5c77bbaa78f3352fdbb53e45bf33e3f6143535445cf0f48600919e733506dcbb06dc734f59d6cc4b69df3876830314da7a2e29c9bd62ef96fef9e07feb1a0792f8122dc94594c406e8b06d62c1dc4fd08c335c3fab0dc8b21431a442d33769eecbf34ae42d97f204fe9fcefe6ee1e7da31f1f3bf3154fe3e77ab3c6b49058b86af882440c6466e28531b8a88ee45dd283b1a67b561366145dfc2f08ba7381a7f77cc1b15dbc2eb3eb0df943839516e2260f35a9b7b6772e242f352ce7038beedacd2a5093d2c5f23bbc992d62c569cf9876e39bd3f20725fbde1d586acbc4380f5e520d4a110f54b24dff035bc47fafe71b65782b91f1b38db2db8bb1e5c1f6447d3c3be0eab2cb0f83694168d1fbc1338c5f523ed454967173ee24eb0fe951a603401d259ceb428bbee043e586e8fb9553eaa86eaa1bba13a10b" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a845d877c0e8c27-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 16:15:54 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "485", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=ypLA4M9G6mnG7MBUSFm_Iglqo2scXgDPcHoPMb.wzeM-1764778554082-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "507", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999976", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_074137d9ba50430ba0f643913c8eaf97" + }, + "responseIsBinary": false }, - "responseIsBinary": false - } -] + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the test_tool with input \"test\", then provide a final response with the word '231'" + }, + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_C0nDyTs9YD4qKYn5vcMcuSTS", + "type": "function", + "function": { + "name": "test_tool", + "arguments": "{\"input\":\"test\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + { + "role": "tool", + "content": "Tool result", + "tool_call_id": "call_C0nDyTs9YD4qKYn5vcMcuSTS" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "test_tool", + "description": "A test tool", + "parameters": { + "type": "object", + "properties": { + "input": { + "type": "string" + } + } + } + } + } + ], + "n": 1, + "stream": false + }, + "status": 200, + "response": [ + "1b2303201c07762c33326c3cb8f92623e696eaeef34c23125d262640832874f54d1d1685a99bf7dce64c63f96f6f0eec295acbd24912166907799b1478f077f5f60d81d001f0e46f765a24d4228cf2599e6ecc7dbf56fafdf27c5e4fab3d57b1f7cdc1c121a0a282d8f801091284cce71b708a2c2a8a2a49e24594110db85f34949853699a51acfa68c91739ff41feccc17f63426fd8262cf9a1ac450a701841a0ca93d685df37f87b5969b4ee7881bbca7fe38f331331ac1b43c321a258f63af72fc8a324f78b2ab76a6c0b7967e941020c8451886638986f85d7ad0e1e8aa5488b460f6e443352a569010b37beb7f9418c88261aa5b4e9d9babb9bf63211d0b603d336ae18cccdef24c1bbc5194a5ed2fc6698f9b7e6774afcdb7a396caadc8294cf4b2448b532f19783bcaa37a15b01940df17b290d6cfd8435627621a8b257e8ae238b82038e69127a" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a845d8ea9d58c27-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 16:15:55 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "379", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=nv4APHcc7JiLRnjDkeab5uhoAoOa3wZ0qYhw8ZbJtUg-1764778555117-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "391", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999971", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_bdb05ea440404ab4b82c83580f7cd7ed" + }, + "responseIsBinary": false + } +] \ No newline at end of file From 337d05e57505a322c62cb81c5689df86a3bf583e Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:25:06 -0500 Subject: [PATCH 17/43] make executable --- examples/tool-calls-beta-zod.ts | 0 examples/tool-helpers-advanced-streaming.ts | 0 examples/tool-helpers-advanced.ts | 0 examples/tool-helpers-json-schema.ts | 0 4 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 examples/tool-calls-beta-zod.ts mode change 100644 => 100755 examples/tool-helpers-advanced-streaming.ts mode change 100644 => 100755 examples/tool-helpers-advanced.ts mode change 100644 => 100755 examples/tool-helpers-json-schema.ts diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts old mode 100644 new mode 100755 diff --git a/examples/tool-helpers-advanced-streaming.ts b/examples/tool-helpers-advanced-streaming.ts old mode 100644 new mode 100755 diff --git a/examples/tool-helpers-advanced.ts b/examples/tool-helpers-advanced.ts old mode 100644 new mode 100755 diff --git a/examples/tool-helpers-json-schema.ts b/examples/tool-helpers-json-schema.ts old mode 100644 new mode 100755 From 410d410ff13c93075dcc9d2bc484e8d0506d512a Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:29:57 -0500 Subject: [PATCH 18/43] tests passing --- src/helpers/beta/zod.ts | 73 +-------------------------------------- tests/utils/mock-fetch.ts | 67 +++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 94 deletions(-) diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 807158175..3307df9ed 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -1,47 +1,7 @@ -import { transformJSONSchema } from '../..//lib/transform-json-schema'; import type { infer as zodInfer, ZodType } from 'zod'; import * as z from 'zod'; -import { OpenAIError } from '../../core/error'; import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; -import type { AutoParseableBetaOutputFormat } from '../../lib/beta-parser'; -import { FunctionTool } from '../../resources/beta'; -// import { AutoParseableBetaOutputFormat } from '../../lib/beta-parser'; -// import { BetaRunnableTool, Promisable } from '../../lib/tools/BetaRunnableTool'; -// import { BetaToolResultContentBlockParam } from '../../resources/beta'; -/** - * Creates a JSON schema output format object from the given Zod schema. - * - * If this is passed to the `.parse()` method then the response message will contain a - * `.parsed` property that is the result of parsing the content with the given Zod object. - * - * This can be passed directly to the `.create()` method but will not - * result in any automatic parsing, you'll have to parse the response yourself. - */ -export function betaZodOutputFormat( - zodObject: ZodInput, -): AutoParseableBetaOutputFormat> { - let jsonSchema = z.toJSONSchema(zodObject, { reused: 'ref' }); - - jsonSchema = transformJSONSchema(jsonSchema); - - return { - type: 'json_schema', - schema: { - ...jsonSchema, - }, - parse: (content) => { - const output = zodObject.safeParse(JSON.parse(content)); - - if (!output.success) { - throw new OpenAIError( - `Failed to parse structured output: ${output.error.message} cause: ${output.error.issues}`, - ); - } - - return output.data; - }, - }; -} +import type { FunctionTool } from '../../resources/beta'; /** * Creates a tool using the provided Zod schema that can be passed @@ -78,34 +38,3 @@ export function betaZodTool(options: { parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, }; } - -// /** -// * Creates a tool using the provided Zod schema that can be passed -// * into the `.toolRunner()` method. The Zod schema will automatically be -// * converted into JSON Schema when passed to the API. The provided function's -// * input arguments will also be validated against the provided schema. -// */ -// export function betaZodTool(options: { -// name: string; -// inputSchema: InputSchema; -// description: string; -// run: (args: zodInfer) => Promisable>; -// }): BetaRunnableTool> { -// const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' }); - -// if (jsonSchema.type !== 'object') { -// throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`); -// } - -// // TypeScript doesn't narrow the type after the runtime check, so we need to assert it -// const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; - -// return { -// type: 'custom', -// name: options.name, -// input_schema: objectSchema, -// description: options.description, -// run: options.run, -// parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, -// }; -// } diff --git a/tests/utils/mock-fetch.ts b/tests/utils/mock-fetch.ts index 365066ba3..6349de911 100644 --- a/tests/utils/mock-fetch.ts +++ b/tests/utils/mock-fetch.ts @@ -1,47 +1,70 @@ -import { Fetch, RequestInfo, RequestInit } from 'openai/internal/builtin-types'; +import { type Fetch, type RequestInfo, type RequestInit, type Response } from 'openai/internal/builtin-types'; import { PassThrough } from 'stream'; +/** + * Creates a mock `fetch` function and a `handleRequest` function for intercepting `fetch` calls. + * + * You call `handleRequest` with a callback function that handles the next `fetch` call. + * It returns a Promise that: + * - waits for the next call to `fetch` + * - calls the callback with the `fetch` arguments + * - resolves `fetch` with the callback output + */ export function mockFetch(): { fetch: Fetch; handleRequest: (handle: Fetch) => void; handleStreamEvents: (events: any[]) => void; handleMessageStreamEvents: (iter: AsyncIterable) => void; } { - const queue: Promise[] = []; - const readResolvers: ((handler: typeof fetch) => void)[] = []; + const fetchQueue: ((handler: typeof fetch) => void)[] = []; + const handlerQueue: Promise[] = []; - let index = 0; + const enqueueHandler = () => { + handlerQueue.push( + new Promise((resolve) => { + fetchQueue.push((handle: typeof fetch) => { + enqueueHandler(); + resolve(handle); + }); + }), + ); + }; + enqueueHandler(); async function fetch(req: string | RequestInfo, init?: RequestInit): Promise { - const idx = index++; - if (!queue[idx]) { - queue.push(new Promise((resolve) => readResolvers.push(resolve))); - } - - const handler = await queue[idx]!; + const handler = await handlerQueue.shift(); + if (!handler) throw new Error('expected handler to be defined'); + const signal = init?.signal; + if (!signal) return await handler(req, init); return await Promise.race([ handler(req, init), - new Promise((_resolve, reject) => { - if (init?.signal?.aborted) { - // @ts-ignore + new Promise((resolve, reject) => { + if (signal.aborted) { + // @ts-ignore does exist in Node reject(new DOMException('The user aborted a request.', 'AbortError')); return; } - init?.signal?.addEventListener('abort', (_e) => { - // @ts-ignore + signal.addEventListener('abort', (e) => { + // @ts-ignore does exist in Node reject(new DOMException('The user aborted a request.', 'AbortError')); }); }), ]); } - function handleRequest(handler: typeof fetch): void { - if (readResolvers.length) { - const resolver = readResolvers.shift()!; - resolver(handler); - return; - } - queue.push(Promise.resolve(handler)); + function handleRequest(handle: typeof fetch): Promise { + return new Promise((resolve, reject) => { + fetchQueue.shift()?.(async (req, init) => { + try { + return await handle(req, init); + } catch (err) { + reject(err); + return err as any; + } finally { + resolve(); + } + }); + }); } function handleStreamEvents(events: any[]) { From 51b200d07b9a6300c77bfd0b2667cc70741683e8 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:42:20 -0500 Subject: [PATCH 19/43] fix type errors --- examples/tool-calls-beta-zod.ts | 1 - src/lib/beta/BetaToolRunner.ts | 2 +- src/lib/transform-json-schema.ts | 124 ----------------------------- tests/lib/tools/ToolRunner.test.ts | 17 ++-- 4 files changed, 9 insertions(+), 135 deletions(-) delete mode 100644 src/lib/transform-json-schema.ts diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts index d2e4fb2ae..18316b102 100755 --- a/examples/tool-calls-beta-zod.ts +++ b/examples/tool-calls-beta-zod.ts @@ -100,7 +100,6 @@ async function main() { console.log(); } } - console.log(JSON.stringify(runner.params.messages, null, 2)); } main(); diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 13b8f42cd..2dc8141f4 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -246,7 +246,7 @@ export class BetaToolRunner { * } */ async generateToolResponse() { - // The most recent message from the assistant. This prev had this.params.messages.at(-1) but I think that's wrong. + // The most recent message from the assistant. TODO: do we want || this.params.messages.at(-1)? const message = await this.#message; if (!message) { return null; diff --git a/src/lib/transform-json-schema.ts b/src/lib/transform-json-schema.ts deleted file mode 100644 index b7132bb68..000000000 --- a/src/lib/transform-json-schema.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { pop } from '../internal/utils'; - -// Supported string formats -const SUPPORTED_STRING_FORMATS = new Set([ - 'date-time', - 'time', - 'date', - 'duration', - 'email', - 'hostname', - 'uri', - 'ipv4', - 'ipv6', - 'uuid', -]); - -export type JSONSchema = Record; - -function deepClone(obj: T): T { - return JSON.parse(JSON.stringify(obj)); -} - -export function transformJSONSchema(jsonSchema: JSONSchema): JSONSchema { - const workingCopy = deepClone(jsonSchema); - return _transformJSONSchema(workingCopy); -} - -function _transformJSONSchema(jsonSchema: JSONSchema): JSONSchema { - const strictSchema: JSONSchema = {}; - - const ref = pop(jsonSchema, '$ref'); - if (ref !== undefined) { - strictSchema['$ref'] = ref; - return strictSchema; - } - - const defs = pop(jsonSchema, '$defs'); - if (defs !== undefined) { - const strictDefs: Record = {}; - strictSchema['$defs'] = strictDefs; - for (const [name, defSchema] of Object.entries(defs)) { - strictDefs[name] = _transformJSONSchema(defSchema as JSONSchema); - } - } - - const type = pop(jsonSchema, 'type'); - const anyOf = pop(jsonSchema, 'anyOf'); - const oneOf = pop(jsonSchema, 'oneOf'); - const allOf = pop(jsonSchema, 'allOf'); - - if (Array.isArray(anyOf)) { - strictSchema['anyOf'] = anyOf.map((variant) => _transformJSONSchema(variant as JSONSchema)); - } else if (Array.isArray(oneOf)) { - strictSchema['anyOf'] = oneOf.map((variant) => _transformJSONSchema(variant as JSONSchema)); - } else if (Array.isArray(allOf)) { - strictSchema['allOf'] = allOf.map((entry) => _transformJSONSchema(entry as JSONSchema)); - } else { - if (type === undefined) { - throw new Error('JSON schema must have a type defined if anyOf/oneOf/allOf are not used'); - } - strictSchema['type'] = type; - } - - const description = pop(jsonSchema, 'description'); - if (description !== undefined) { - strictSchema['description'] = description; - } - - const title = pop(jsonSchema, 'title'); - if (title !== undefined) { - strictSchema['title'] = title; - } - - if (type === 'object') { - const properties = pop(jsonSchema, 'properties') || {}; - - strictSchema['properties'] = Object.fromEntries( - Object.entries(properties).map(([key, propSchema]) => [ - key, - _transformJSONSchema(propSchema as JSONSchema), - ]), - ); - - pop(jsonSchema, 'additionalProperties'); - strictSchema['additionalProperties'] = false; - - const required = pop(jsonSchema, 'required'); - if (required !== undefined) { - strictSchema['required'] = required; - } - } else if (type === 'string') { - const format = pop(jsonSchema, 'format'); - if (format !== undefined && SUPPORTED_STRING_FORMATS.has(format)) { - strictSchema['format'] = format; - } else if (format !== undefined) { - jsonSchema['format'] = format; - } - } else if (type === 'array') { - const items = pop(jsonSchema, 'items'); - if (items !== undefined) { - strictSchema['items'] = _transformJSONSchema(items as JSONSchema); - } - - const minItems = pop(jsonSchema, 'minItems'); - if (minItems !== undefined && (minItems === 0 || minItems === 1)) { - strictSchema['minItems'] = minItems; - } else if (minItems !== undefined) { - jsonSchema['minItems'] = minItems; - } - } - - if (Object.keys(jsonSchema).length > 0) { - const existingDescription = strictSchema['description']; - strictSchema['description'] = - (existingDescription ? existingDescription + '\n\n' : '') + - '{' + - Object.entries(jsonSchema) - .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) - .join(', ') + - '}'; - } - - return strictSchema; -} diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/ToolRunner.test.ts index ae18b8164..4c7ef4dce 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/ToolRunner.test.ts @@ -1,7 +1,7 @@ import OpenAI from 'openai'; import { mockFetch } from '../../utils/mock-fetch'; -import { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; -import { +import type { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; +import type { ChatCompletion, ChatCompletionChunk, ChatCompletionMessage, @@ -9,7 +9,8 @@ import { ChatCompletionMessageToolCall, ChatCompletionToolMessageParam, } from 'openai/resources'; -import { Fetch } from 'openai/internal/builtin-types'; +import type { Fetch } from 'openai/internal/builtin-types'; +import type { BetaToolRunnerParams } from 'openai/lib/beta/BetaToolRunner'; const weatherTool: BetaRunnableTool<{ location: string }> = { type: 'function', @@ -286,13 +287,11 @@ interface SetupTestResult { handleAssistantMessageStream: (messageContentOrToolCalls?: ToolCallsOrMessage) => ChatCompletion; } -type ToolRunnerParams = Parameters[0]; - type ToolCallsOrMessage = ChatCompletionMessageToolCall[] | ChatCompletionMessage; -function setupTest(params?: Partial & { stream?: false }): SetupTestResult; -function setupTest(params: Partial & { stream: true }): SetupTestResult; -function setupTest(params: Partial = {}): SetupTestResult { +function setupTest(params?: Partial & { stream?: false }): SetupTestResult; +function setupTest(params: Partial & { stream: true }): SetupTestResult; +function setupTest(params: Partial = {}): SetupTestResult { const { handleRequest, handleStreamEvents, fetch } = mockFetch(); let messageIdCounter = 0; const handleAssistantMessage: SetupTestResult['handleAssistantMessage'] = ( @@ -380,7 +379,7 @@ function setupTest(params: Partial = {}): SetupTestResult Date: Wed, 3 Dec 2025 11:43:40 -0500 Subject: [PATCH 20/43] unformat mistakenly formatted jsons --- .../embeddings-base64-response.json | 13 +---- .../embeddings-float-response.json | 50 +------------------ 2 files changed, 2 insertions(+), 61 deletions(-) diff --git a/tests/api-resources/embeddings-base64-response.json b/tests/api-resources/embeddings-base64-response.json index 9e552d5a1..9b0f7629c 100644 --- a/tests/api-resources/embeddings-base64-response.json +++ b/tests/api-resources/embeddings-base64-response.json @@ -1,12 +1 @@ -{ - "object": "list", - "data": [ - { - "object": "embedding", - "index": 0, - "embedding": "A1fLvaC4Bb0QB7w8yEvrPOm9Xj2r0yA8EW4sPRq75j3Fbiq81/chPumAGb0afqG8R6AFvpzsQT35SPO7Hi39PEMAir1lf0A92McfvRoVlLxQv9o9tHqIvQYlrL0fwlK8sufPPYz2gjzH5Ho93GebvN+eCTxjRjW8PJRKvXMtFD4+n3C9ByMPO39Gkjs1Jm49A1fLPdNXpjv8RLm92McfveKpLz01VNO9SUIevhAHvD0flG09+9srvW5j7Txp8dY8LW4Ju08bJb1GdL29g+aNPWlLBD1p8dY8LkCkvfPLtjxcBj4+1/ehPebv/bz/Ifo8SqkOvREFHzyAr588HbUPPbFS+r00gri825WAPQlcGj1qHZ+8o8EOPo880Tn5dli9zRUSPc2APD0b5RG9mhxEvTyUSj3FQMU95u/9vE20tD3wwBC94NmxvXSUhL3Ofh8904WLPRbeJb2Paja8BClmvhwgOj2e6Ic9em0LPdj1BD3lSau7dJQEPJi107yB6kc97sTKO6lAaD2YDwE9YDuPPSFVC735dtg9SK1IOysJNrwtQkE8BmJxPb2ZXT0hVYs9g+YNvLfuuz2nyhe9z7nHN5UVWDxea5E77F1avTIbyL256oG9ft+hPVWJAbwNoug82TCtvUrm072wgN86JPWGO3TRyTwOY4a8xJwPvkx5DL1f1B68RwkTvja7Q72BrQI9Pfs6PTdfeb3RxG09jJxVvfl22D3eCbQ9FbR6vTPtYrn0mzS+kqGkPDxXhbwyG8i98M9wveayuL1EpL88lNqvve3yL70RQmQ7VcZGPaPBjr1wyEA9fKaWOskMibwNomi8J9Rku9EeGz016Si8O1mivQ38lb0EgxO88P1VvcilmLuNA0a9lj8DvHCceD3lSSs9uFWsve6HBT6XEZ68ShS5PFJSE70dTIK86OvDvSNgsbzS8DU8bPz8PAuVpTxKQIE9/NmOPBhFFj7LsL67PJRKvIxu8LwSqVS8D8yTPSOOlj1g0gG8A+69vYz2AjxPhLK80fLSPbrL/LztWz09LAcZvqfKF73B/JO8lnzIvCk5OLxwMU69dmQCvQtp3bs6hwe9WZKKume4S7x3CLg9zK4hPLsjDT16P6a7MbTXPRp+IT0dtQ89GayGvcngwD2F8bO70R4bu8tFlDxcBr67xAWdvdnWfzzQTIC9zn6fPYSKwz3alx28h8GxPW74wj3eNxk+xUBFvIpjyj0WdRi9AkoIPXhvqLugx+U8F0ezvUlCHjx3NAC9uvlhPEOmXD36oAM9D56uvddgrz2giiC9GhWUvHrWGLv0yRk8fOPbvMc+KLs7//S8v5UjPJUV2D0KLjW6YKa5PDciNDuJznQ9USZLPQ==" - } - ], - "model": "text-embedding-3-large", - "usage": { "prompt_tokens": 1, "total_tokens": 1 } -} +{"object":"list","data":[{"object":"embedding","index":0,"embedding":"A1fLvaC4Bb0QB7w8yEvrPOm9Xj2r0yA8EW4sPRq75j3Fbiq81/chPumAGb0afqG8R6AFvpzsQT35SPO7Hi39PEMAir1lf0A92McfvRoVlLxQv9o9tHqIvQYlrL0fwlK8sufPPYz2gjzH5Ho93GebvN+eCTxjRjW8PJRKvXMtFD4+n3C9ByMPO39Gkjs1Jm49A1fLPdNXpjv8RLm92McfveKpLz01VNO9SUIevhAHvD0flG09+9srvW5j7Txp8dY8LW4Ju08bJb1GdL29g+aNPWlLBD1p8dY8LkCkvfPLtjxcBj4+1/ehPebv/bz/Ifo8SqkOvREFHzyAr588HbUPPbFS+r00gri825WAPQlcGj1qHZ+8o8EOPo880Tn5dli9zRUSPc2APD0b5RG9mhxEvTyUSj3FQMU95u/9vE20tD3wwBC94NmxvXSUhL3Ofh8904WLPRbeJb2Paja8BClmvhwgOj2e6Ic9em0LPdj1BD3lSau7dJQEPJi107yB6kc97sTKO6lAaD2YDwE9YDuPPSFVC735dtg9SK1IOysJNrwtQkE8BmJxPb2ZXT0hVYs9g+YNvLfuuz2nyhe9z7nHN5UVWDxea5E77F1avTIbyL256oG9ft+hPVWJAbwNoug82TCtvUrm072wgN86JPWGO3TRyTwOY4a8xJwPvkx5DL1f1B68RwkTvja7Q72BrQI9Pfs6PTdfeb3RxG09jJxVvfl22D3eCbQ9FbR6vTPtYrn0mzS+kqGkPDxXhbwyG8i98M9wveayuL1EpL88lNqvve3yL70RQmQ7VcZGPaPBjr1wyEA9fKaWOskMibwNomi8J9Rku9EeGz016Si8O1mivQ38lb0EgxO88P1VvcilmLuNA0a9lj8DvHCceD3lSSs9uFWsve6HBT6XEZ68ShS5PFJSE70dTIK86OvDvSNgsbzS8DU8bPz8PAuVpTxKQIE9/NmOPBhFFj7LsL67PJRKvIxu8LwSqVS8D8yTPSOOlj1g0gG8A+69vYz2AjxPhLK80fLSPbrL/LztWz09LAcZvqfKF73B/JO8lnzIvCk5OLxwMU69dmQCvQtp3bs6hwe9WZKKume4S7x3CLg9zK4hPLsjDT16P6a7MbTXPRp+IT0dtQ89GayGvcngwD2F8bO70R4bu8tFlDxcBr67xAWdvdnWfzzQTIC9zn6fPYSKwz3alx28h8GxPW74wj3eNxk+xUBFvIpjyj0WdRi9AkoIPXhvqLugx+U8F0ezvUlCHjx3NAC9uvlhPEOmXD36oAM9D56uvddgrz2giiC9GhWUvHrWGLv0yRk8fOPbvMc+KLs7//S8v5UjPJUV2D0KLjW6YKa5PDciNDuJznQ9USZLPQ=="}],"model":"text-embedding-3-large","usage":{"prompt_tokens":1,"total_tokens":1}} \ No newline at end of file diff --git a/tests/api-resources/embeddings-float-response.json b/tests/api-resources/embeddings-float-response.json index bf179a36e..9b5b788e2 100644 --- a/tests/api-resources/embeddings-float-response.json +++ b/tests/api-resources/embeddings-float-response.json @@ -1,49 +1 @@ -{ - "object": "list", - "data": [ - { - "object": "embedding", - "index": 0, - "embedding": [ - -0.099287055, -0.032646775, 0.022952586, 0.028722659, 0.05438033, 0.009816091, 0.042097155, - 0.112661555, -0.010402386, 0.158172, -0.037476454, -0.01971345, -0.13049422, 0.04734479, - -0.0074244705, 0.030905303, -0.06738331, 0.046996493, -0.039008945, -0.018076468, 0.10681021, - -0.06664029, -0.08405499, -0.012863665, 0.10151614, 0.015986703, 0.061253335, -0.018970422, - 0.008399694, -0.011064145, -0.049457774, 0.14470463, -0.058745615, 0.0021840946, 0.00446397, - 0.058141906, 0.099287055, 0.0050763874, -0.09046361, -0.039008945, 0.042886622, -0.103187956, - -0.15454973, 0.091810346, 0.058002587, -0.041957837, 0.028978076, 0.02623816, -0.002097021, - -0.040309247, -0.09250693, 0.06928732, 0.03229848, 0.02623816, -0.08020054, 0.022314047, 0.18557113, - 0.079086, -0.030998182, 0.030533789, -0.034829415, 0.009705798, 0.019492865, 0.035084832, - -0.122228034, -0.022523023, 0.06278583, 0.037685428, -0.019423205, 0.13941054, 0.00039908706, - -0.052847836, 0.035665322, 0.04602127, -0.035618883, -0.04787884, 0.049457774, 0.096314944, - -0.030998182, 0.08823452, -0.03534025, -0.086841345, -0.06473628, 0.03893929, 0.06812634, -0.040495, - -0.011133804, -0.22476584, 0.045440778, 0.06636165, 0.03403995, 0.032461017, -0.005227315, - 0.008092035, -0.025843427, 0.048807625, 0.0061880266, 0.05670229, 0.031509012, 0.06993747, - -0.034016732, 0.10569567, 0.0030620862, -0.011110584, 0.011795563, 0.058931373, 0.054101694, - 0.068033464, -0.008660915, 0.091763906, -0.0370585, 0.000023809172, 0.013188739, 0.004437848, - -0.053312227, -0.09770812, -0.06343598, 0.07903956, -0.007906278, 0.028397584, -0.084565826, - -0.103466585, 0.0017051902, 0.0041185785, 0.024636008, -0.016404655, -0.14024645, -0.034295365, - -0.009694188, -0.14359008, -0.04778596, 0.031903747, 0.045649756, -0.06088182, 0.058049027, - -0.052151248, 0.10569567, 0.087909445, -0.061206896, -0.00021641403, -0.17637616, 0.020096574, - -0.016276948, -0.09770812, -0.058792055, -0.09018497, 0.023393758, -0.08586612, -0.04295628, - 0.0034829418, 0.048528988, -0.06970527, 0.047066152, 0.0011493708, -0.01672973, -0.014198792, - -0.0034916492, 0.037871186, -0.010309507, -0.079271756, -0.073234655, -0.0090034045, -0.052244127, - -0.0046584345, -0.04834323, -0.008010766, 0.060696065, 0.04181852, -0.08414787, 0.13040134, - -0.019295497, 0.022592682, -0.03596718, -0.015905434, -0.0956648, -0.021652287, 0.011104779, - 0.030882083, 0.02021267, 0.0631109, 0.017437927, 0.14674795, -0.005819415, -0.012364443, -0.029349588, - -0.012979763, 0.072166555, 0.07351329, -0.007923692, -0.09273913, 0.007993352, -0.021791605, - 0.1030022, -0.030858863, 0.046230245, -0.14944142, -0.0370585, -0.018064858, -0.02447347, - -0.011244097, -0.050340116, -0.03183409, -0.006756907, -0.033087946, -0.001057218, -0.012434102, - 0.089859895, 0.009868335, 0.034457903, -0.005073485, 0.10532416, 0.0394269, 0.035084832, -0.06575794, - 0.09417874, -0.005491438, -0.002366949, 0.018099686, -0.005799098, -0.07667115, 0.0156151885, - -0.06264651, 0.07787858, 0.09547904, -0.009618724, 0.086794905, 0.095200405, 0.14962718, -0.012039368, - 0.09882267, -0.037221037, 0.033273704, -0.0051402412, 0.02804929, -0.08753794, 0.009659358, - -0.031300034, 0.01379245, 0.053869497, 0.03213594, -0.08526241, 0.085633926, -0.039194703, - -0.018076468, -0.0023321197, 0.009386528, -0.026841871, -0.0025672184, -0.02990686, 0.009984433, - 0.105509914, -0.00069114624, 0.022662342, 0.0027486214, 0.05976728, 0.04959709 - ] - } - ], - "model": "text-embedding-3-large", - "usage": { "prompt_tokens": 1, "total_tokens": 1 } -} +{"object":"list","data":[{"object":"embedding","index":0,"embedding":[-0.099287055,-0.032646775,0.022952586,0.028722659,0.05438033,0.009816091,0.042097155,0.112661555,-0.010402386,0.158172,-0.037476454,-0.01971345,-0.13049422,0.04734479,-0.0074244705,0.030905303,-0.06738331,0.046996493,-0.039008945,-0.018076468,0.10681021,-0.06664029,-0.08405499,-0.012863665,0.10151614,0.015986703,0.061253335,-0.018970422,0.008399694,-0.011064145,-0.049457774,0.14470463,-0.058745615,0.0021840946,0.00446397,0.058141906,0.099287055,0.0050763874,-0.09046361,-0.039008945,0.042886622,-0.103187956,-0.15454973,0.091810346,0.058002587,-0.041957837,0.028978076,0.02623816,-0.002097021,-0.040309247,-0.09250693,0.06928732,0.03229848,0.02623816,-0.08020054,0.022314047,0.18557113,0.079086,-0.030998182,0.030533789,-0.034829415,0.009705798,0.019492865,0.035084832,-0.122228034,-0.022523023,0.06278583,0.037685428,-0.019423205,0.13941054,0.00039908706,-0.052847836,0.035665322,0.04602127,-0.035618883,-0.04787884,0.049457774,0.096314944,-0.030998182,0.08823452,-0.03534025,-0.086841345,-0.06473628,0.03893929,0.06812634,-0.040495,-0.011133804,-0.22476584,0.045440778,0.06636165,0.03403995,0.032461017,-0.005227315,0.008092035,-0.025843427,0.048807625,0.0061880266,0.05670229,0.031509012,0.06993747,-0.034016732,0.10569567,0.0030620862,-0.011110584,0.011795563,0.058931373,0.054101694,0.068033464,-0.008660915,0.091763906,-0.0370585,0.000023809172,0.013188739,0.004437848,-0.053312227,-0.09770812,-0.06343598,0.07903956,-0.007906278,0.028397584,-0.084565826,-0.103466585,0.0017051902,0.0041185785,0.024636008,-0.016404655,-0.14024645,-0.034295365,-0.009694188,-0.14359008,-0.04778596,0.031903747,0.045649756,-0.06088182,0.058049027,-0.052151248,0.10569567,0.087909445,-0.061206896,-0.00021641403,-0.17637616,0.020096574,-0.016276948,-0.09770812,-0.058792055,-0.09018497,0.023393758,-0.08586612,-0.04295628,0.0034829418,0.048528988,-0.06970527,0.047066152,0.0011493708,-0.01672973,-0.014198792,-0.0034916492,0.037871186,-0.010309507,-0.079271756,-0.073234655,-0.0090034045,-0.052244127,-0.0046584345,-0.04834323,-0.008010766,0.060696065,0.04181852,-0.08414787,0.13040134,-0.019295497,0.022592682,-0.03596718,-0.015905434,-0.0956648,-0.021652287,0.011104779,0.030882083,0.02021267,0.0631109,0.017437927,0.14674795,-0.005819415,-0.012364443,-0.029349588,-0.012979763,0.072166555,0.07351329,-0.007923692,-0.09273913,0.007993352,-0.021791605,0.1030022,-0.030858863,0.046230245,-0.14944142,-0.0370585,-0.018064858,-0.02447347,-0.011244097,-0.050340116,-0.03183409,-0.006756907,-0.033087946,-0.001057218,-0.012434102,0.089859895,0.009868335,0.034457903,-0.005073485,0.10532416,0.0394269,0.035084832,-0.06575794,0.09417874,-0.005491438,-0.002366949,0.018099686,-0.005799098,-0.07667115,0.0156151885,-0.06264651,0.07787858,0.09547904,-0.009618724,0.086794905,0.095200405,0.14962718,-0.012039368,0.09882267,-0.037221037,0.033273704,-0.0051402412,0.02804929,-0.08753794,0.009659358,-0.031300034,0.01379245,0.053869497,0.03213594,-0.08526241,0.085633926,-0.039194703,-0.018076468,-0.0023321197,0.009386528,-0.026841871,-0.0025672184,-0.02990686,0.009984433,0.105509914,-0.00069114624,0.022662342,0.0027486214,0.05976728,0.04959709]}],"model":"text-embedding-3-large","usage":{"prompt_tokens":1,"total_tokens":1}} \ No newline at end of file From 4a23c9d4ad727ff5cf8610d7af487813bd73895d Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:45:40 -0500 Subject: [PATCH 21/43] make nock dev dep --- package.json | 4 ++-- yarn.lock | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index e934a2545..5f07ac294 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,7 @@ "fix": "./scripts/format" }, "dependencies": { - "json-schema-to-ts": "3.1.1", - "nock": "^14.0.10" + "json-schema-to-ts": "3.1.1" }, "devDependencies": { "@arethetypeswrong/cli": "^0.17.0", @@ -48,6 +47,7 @@ "fast-check": "^3.22.0", "iconv-lite": "^0.6.3", "jest": "^29.4.0", + "nock": "^14.0.10", "prettier": "^3.0.0", "publint": "^0.2.12", "ts-jest": "^29.1.0", diff --git a/yarn.lock b/yarn.lock index ed41fb0fa..689239475 100644 --- a/yarn.lock +++ b/yarn.lock @@ -700,7 +700,7 @@ "@mswjs/interceptors@^0.39.5": version "0.39.8" - resolved "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.39.8.tgz" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.39.8.tgz#0a2cf4cf26a731214ca4156273121f67dff7ebf8" integrity sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA== dependencies: "@open-draft/deferred-promise" "^2.2.0" @@ -733,12 +733,12 @@ "@open-draft/deferred-promise@^2.2.0": version "2.2.0" - resolved "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== "@open-draft/logger@^0.3.0": version "0.3.0" - resolved "https://registry.npmjs.org/@open-draft/logger/-/logger-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== dependencies: is-node-process "^1.2.0" @@ -746,7 +746,7 @@ "@open-draft/until@^2.0.0": version "2.1.0" - resolved "https://registry.npmjs.org/@open-draft/until/-/until-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== "@pkgr/core@^0.2.4": @@ -2040,7 +2040,7 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: is-node-process@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/is-node-process/-/is-node-process-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== is-number@^7.0.0: @@ -2524,7 +2524,7 @@ json-stable-stringify-without-jsonify@^1.0.1: json-stringify-safe@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== json5@^2.2.2, json5@^2.2.3: @@ -2727,7 +2727,7 @@ natural-compare@^1.4.0: nock@^14.0.10: version "14.0.10" - resolved "https://registry.npmjs.org/nock/-/nock-14.0.10.tgz" + resolved "https://registry.yarnpkg.com/nock/-/nock-14.0.10.tgz#d6f4e73e1c6b4b7aa19d852176e68940e15cd19d" integrity sha512-Q7HjkpyPeLa0ZVZC5qpxBt5EyLczFJ91MEewQiIi9taWuA0KB/MDJlUWtON+7dGouVdADTQsf9RA7TZk6D8VMw== dependencies: "@mswjs/interceptors" "^0.39.5" @@ -2821,7 +2821,7 @@ optionator@^0.9.3: outvariant@^1.4.0, outvariant@^1.4.3: version "1.4.3" - resolved "https://registry.npmjs.org/outvariant/-/outvariant-1.4.3.tgz" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== p-all@^3.0.0: @@ -2983,7 +2983,7 @@ prompts@^2.0.1: propagate@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== publint@^0.2.12: @@ -3172,7 +3172,7 @@ stack-utils@^2.0.3: strict-event-emitter@^0.5.1: version "0.5.1" - resolved "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== string-length@^4.0.1: From 444f9b0728f93841b66d0dd76a4692b9c1ff466d Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 11:46:27 -0500 Subject: [PATCH 22/43] more minimal package changes --- package.json | 2 +- yarn.lock | 981 ++++++++++++++++++++++++++------------------------- 2 files changed, 507 insertions(+), 476 deletions(-) diff --git a/package.json b/package.json index 5f07ac294..275e424d9 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "fix": "./scripts/format" }, "dependencies": { - "json-schema-to-ts": "3.1.1" + "json-schema-to-ts": "^3.1.1" }, "devDependencies": { "@arethetypeswrong/cli": "^0.17.0", diff --git a/yarn.lock b/yarn.lock index 689239475..08789ee72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4,12 +4,12 @@ "@aashutoshrathi/word-wrap@^1.2.3": version "1.2.6" - resolved "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== "@ampproject/remapping@^2.2.0": version "2.2.1" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== dependencies: "@jridgewell/gen-mapping" "^0.3.0" @@ -17,12 +17,12 @@ "@andrewbranch/untar.js@^1.0.3": version "1.0.3" - resolved "https://registry.npmjs.org/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/@andrewbranch/untar.js/-/untar.js-1.0.3.tgz#ba9494f85eb83017c5c855763969caf1d0adea00" integrity sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw== "@arethetypeswrong/cli@^0.17.0": version "0.17.0" - resolved "https://registry.npmjs.org/@arethetypeswrong/cli/-/cli-0.17.0.tgz" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/cli/-/cli-0.17.0.tgz#f97f10926b3f9f9eb5117550242d2e06c25cadac" integrity sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA== dependencies: "@arethetypeswrong/core" "0.17.0" @@ -35,7 +35,7 @@ "@arethetypeswrong/core@0.17.0": version "0.17.0" - resolved "https://registry.npmjs.org/@arethetypeswrong/core/-/core-0.17.0.tgz" + resolved "https://registry.yarnpkg.com/@arethetypeswrong/core/-/core-0.17.0.tgz#abb3b5f425056d37193644c2a2de4aecf866b76b" integrity sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA== dependencies: "@andrewbranch/untar.js" "^1.0.3" @@ -48,7 +48,7 @@ "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": version "7.23.5" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== dependencies: "@babel/highlight" "^7.23.4" @@ -56,12 +56,12 @@ "@babel/compat-data@^7.23.5": version "7.23.5" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== "@babel/core@^7.11.6", "@babel/core@^7.12.3": version "7.23.6" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.23.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.6.tgz#8be77cd77c55baadcc1eae1c33df90ab6d2151d4" integrity sha512-FxpRyGjrMJXh7X3wGLGhNDCRiwpWEF74sKjTLDJSG5Kyvow3QZaG0Adbqzi9ZrVjTWpsX+2cxWXD71NMg93kdw== dependencies: "@ampproject/remapping" "^2.2.0" @@ -82,7 +82,7 @@ "@babel/generator@^7.23.6", "@babel/generator@^7.7.2": version "7.23.6" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== dependencies: "@babel/types" "^7.23.6" @@ -92,7 +92,7 @@ "@babel/helper-compilation-targets@^7.23.6": version "7.23.6" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== dependencies: "@babel/compat-data" "^7.23.5" @@ -103,12 +103,12 @@ "@babel/helper-environment-visitor@^7.22.20": version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== "@babel/helper-function-name@^7.23.0": version "7.23.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== dependencies: "@babel/template" "^7.22.15" @@ -116,21 +116,21 @@ "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== dependencies: "@babel/types" "^7.22.5" "@babel/helper-module-imports@^7.22.15": version "7.22.15" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== dependencies: "@babel/types" "^7.22.15" "@babel/helper-module-transforms@^7.23.3": version "7.23.3" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== dependencies: "@babel/helper-environment-visitor" "^7.22.20" @@ -141,41 +141,41 @@ "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== "@babel/helper-simple-access@^7.22.5": version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== dependencies: "@babel/types" "^7.22.5" "@babel/helper-split-export-declaration@^7.22.6": version "7.22.6" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== dependencies: "@babel/types" "^7.22.5" "@babel/helper-string-parser@^7.23.4": version "7.23.4" - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== "@babel/helper-validator-option@^7.23.5": version "7.23.5" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== "@babel/helpers@^7.23.6": version "7.23.6" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.6.tgz#d03af2ee5fb34691eec0cda90f5ecbb4d4da145a" integrity sha512-wCfsbN4nBidDRhpDhvcKlzHWCTlgJYUUdSJfzXb2NuBssDSIjc3xcb+znA7l+zYsFljAcGM0aFkN40cR3lXiGA== dependencies: "@babel/template" "^7.22.15" @@ -184,7 +184,7 @@ "@babel/highlight@^7.23.4": version "7.23.4" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== dependencies: "@babel/helper-validator-identifier" "^7.22.20" @@ -193,115 +193,115 @@ "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": version "7.23.6" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-bigint@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.7.2": version "7.23.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": version "7.23.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== dependencies: "@babel/helper-plugin-utils" "^7.22.5" "@babel/runtime@^7.18.3": version "7.28.4" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== "@babel/template@^7.22.15", "@babel/template@^7.3.3": version "7.22.15" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== dependencies: "@babel/code-frame" "^7.22.13" @@ -310,7 +310,7 @@ "@babel/traverse@^7.23.6": version "7.23.6" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.6.tgz#b53526a2367a0dd6edc423637f3d2d0f2521abc5" integrity sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ== dependencies: "@babel/code-frame" "^7.23.5" @@ -326,7 +326,7 @@ "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": version "7.23.6" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== dependencies: "@babel/helper-string-parser" "^7.23.4" @@ -335,41 +335,41 @@ "@bcoe/v8-coverage@^0.2.3": version "0.2.3" - resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== "@colors/colors@1.5.0": version "1.5.0" - resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" - resolved "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== "@cspotcode/source-map-support@0.7.0": version "0.7.0" - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== dependencies: "@cspotcode/source-map-consumer" "0.8.0" "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" - resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== dependencies: eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.1" - resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== "@eslint/config-array@^0.19.0": version "0.19.2" - resolved "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== dependencies: "@eslint/object-schema" "^2.1.6" @@ -378,21 +378,21 @@ "@eslint/core@^0.10.0": version "0.10.0" - resolved "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.10.0.tgz#23727063c21b335f752dbb3a16450f6f9cbc9091" integrity sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw== dependencies: "@types/json-schema" "^7.0.15" "@eslint/core@^0.11.0": version "0.11.0" - resolved "https://registry.npmjs.org/@eslint/core/-/core-0.11.0.tgz" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.11.0.tgz#7a9226e850922e42cbd2ba71361eacbe74352a12" integrity sha512-DWUB2pksgNEb6Bz2fggIy1wh6fGgZP4Xyy/Mt0QZPiloKKXerbqq9D3SBQTlCRYOrcRPu4vuz+CGjwdfqxnoWA== dependencies: "@types/json-schema" "^7.0.15" "@eslint/eslintrc@^3.2.0": version "3.2.0" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.2.0.tgz#57470ac4e2e283a6bf76044d63281196e370542c" integrity sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w== dependencies: ajv "^6.12.4" @@ -407,17 +407,17 @@ "@eslint/js@9.20.0": version "9.20.0" - resolved "https://registry.npmjs.org/@eslint/js/-/js-9.20.0.tgz" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.20.0.tgz#7421bcbe74889fcd65d1be59f00130c289856eb4" integrity sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ== "@eslint/object-schema@^2.1.6": version "2.1.6" - resolved "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== "@eslint/plugin-kit@^0.2.5": version "0.2.5" - resolved "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz#ee07372035539e7847ef834e3f5e7b79f09e3a81" integrity sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A== dependencies: "@eslint/core" "^0.10.0" @@ -425,12 +425,12 @@ "@humanfs/core@^0.19.1": version "0.19.1" - resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== "@humanfs/node@^0.16.6": version "0.16.6" - resolved "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== dependencies: "@humanfs/core" "^0.19.1" @@ -438,22 +438,22 @@ "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" - resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/retry@^0.3.0": version "0.3.1" - resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== "@humanwhocodes/retry@^0.4.1": version "0.4.1" - resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.1.tgz#9a96ce501bc62df46c4031fbd970e3cc6b10f07b" integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== dependencies: camelcase "^5.3.1" @@ -464,12 +464,12 @@ "@istanbuljs/schema@^0.1.2": version "0.1.3" - resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== "@jest/console@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== dependencies: "@jest/types" "^29.6.3" @@ -481,7 +481,7 @@ "@jest/core@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== dependencies: "@jest/console" "^29.7.0" @@ -515,14 +515,14 @@ "@jest/create-cache-key-function@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz#793be38148fab78e65f40ae30c36785f4ad859f0" integrity sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA== dependencies: "@jest/types" "^29.6.3" "@jest/environment@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== dependencies: "@jest/fake-timers" "^29.7.0" @@ -532,14 +532,14 @@ "@jest/expect-utils@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== dependencies: jest-get-type "^29.6.3" "@jest/expect@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== dependencies: expect "^29.7.0" @@ -547,7 +547,7 @@ "@jest/fake-timers@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== dependencies: "@jest/types" "^29.6.3" @@ -559,7 +559,7 @@ "@jest/globals@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== dependencies: "@jest/environment" "^29.7.0" @@ -569,7 +569,7 @@ "@jest/reporters@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== dependencies: "@bcoe/v8-coverage" "^0.2.3" @@ -599,14 +599,14 @@ "@jest/schemas@^29.6.3": version "29.6.3" - resolved "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== dependencies: "@sinclair/typebox" "^0.27.8" "@jest/source-map@^29.6.3": version "29.6.3" - resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== dependencies: "@jridgewell/trace-mapping" "^0.3.18" @@ -615,7 +615,7 @@ "@jest/test-result@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== dependencies: "@jest/console" "^29.7.0" @@ -625,7 +625,7 @@ "@jest/test-sequencer@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== dependencies: "@jest/test-result" "^29.7.0" @@ -635,7 +635,7 @@ "@jest/transform@^29.7.0": version "29.7.0" - resolved "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== dependencies: "@babel/core" "^7.11.6" @@ -656,7 +656,7 @@ "@jest/types@^29.6.3": version "29.6.3" - resolved "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== dependencies: "@jest/schemas" "^29.6.3" @@ -668,7 +668,7 @@ "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.3" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== dependencies: "@jridgewell/set-array" "^1.0.1" @@ -677,22 +677,22 @@ "@jridgewell/resolve-uri@^3.1.0": version "3.1.1" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== "@jridgewell/set-array@^1.0.1": version "1.1.2" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": version "0.3.20" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== dependencies: "@jridgewell/resolve-uri" "^3.1.0" @@ -712,7 +712,7 @@ "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -720,12 +720,12 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" @@ -751,29 +751,29 @@ "@pkgr/core@^0.2.4": version "0.2.4" - resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.4.tgz#d897170a2b0ba51f78a099edccd968f7b103387c" integrity sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw== "@sinclair/typebox@^0.27.8": version "0.27.8" - resolved "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== "@sindresorhus/is@^4.6.0": version "4.6.0" - resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== "@sinonjs/commons@^3.0.0": version "3.0.0" - resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.0.tgz#beb434fe875d965265e04722ccfc21df7f755d72" integrity sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA== dependencies: type-detect "4.0.8" "@sinonjs/fake-timers@^10.0.2": version "10.3.0" - resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== dependencies: "@sinonjs/commons" "^3.0.0" @@ -805,12 +805,12 @@ "@swc/core-linux-x64-gnu@1.4.16": version "1.4.16" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.16.tgz" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.16.tgz#71eb108b784f9d551ee8a35ebcdaed972f567981" integrity sha512-UUjaW5VTngZYDcA8yQlrFmqs1tLi1TxbKlnaJwoNhel9zRQ0yG1YEVGrzTvv4YApSuIiDK18t+Ip927bwucuVQ== "@swc/core-linux-x64-musl@1.4.16": version "1.4.16" - resolved "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.16.tgz" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.16.tgz#10dbaedb4e3dfc7268e3a9a66ad3431471ef035b" integrity sha512-aFhxPifevDTwEDKPi4eRYWzC0p/WYJeiFkkpNU5Uc7a7M5iMWPAbPFUbHesdlb9Jfqs5c07oyz86u+/HySBNPQ== "@swc/core-win32-arm64-msvc@1.4.16": @@ -830,7 +830,7 @@ "@swc/core@^1.3.102": version "1.4.16" - resolved "https://registry.npmjs.org/@swc/core/-/core-1.4.16.tgz" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.4.16.tgz#d175bae2acfecd53bcbd4293f1fba5ec316634a0" integrity sha512-Xaf+UBvW6JNuV131uvSNyMXHn+bh6LyKN4tbv7tOUFQpXyz/t9YWRE04emtlUW9Y0qrm/GKFCbY8n3z6BpZbTA== dependencies: "@swc/counter" "^0.1.2" @@ -849,12 +849,12 @@ "@swc/counter@^0.1.2", "@swc/counter@^0.1.3": version "0.1.3" - resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" + resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== "@swc/jest@^0.2.29": version "0.2.36" - resolved "https://registry.npmjs.org/@swc/jest/-/jest-0.2.36.tgz" + resolved "https://registry.yarnpkg.com/@swc/jest/-/jest-0.2.36.tgz#2797450a30d28b471997a17e901ccad946fe693e" integrity sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw== dependencies: "@jest/create-cache-key-function" "^29.7.0" @@ -863,34 +863,34 @@ "@swc/types@^0.1.5": version "0.1.6" - resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz" + resolved "https://registry.yarnpkg.com/@swc/types/-/types-0.1.6.tgz#2f13f748995b247d146de2784d3eb7195410faba" integrity sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg== dependencies: "@swc/counter" "^0.1.3" "@tsconfig/node10@^1.0.7": version "1.0.8" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== "@tsconfig/node12@^1.0.7": version "1.0.9" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== "@tsconfig/node14@^1.0.0": version "1.0.1" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== "@tsconfig/node16@^1.0.2": version "1.0.2" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== "@types/babel__core@^7.1.14": version "7.20.5" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== dependencies: "@babel/parser" "^7.20.7" @@ -901,14 +901,14 @@ "@types/babel__generator@*": version "7.6.8" - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": version "7.4.4" - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== dependencies: "@babel/parser" "^7.1.0" @@ -916,45 +916,45 @@ "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": version "7.20.4" - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.4.tgz#ec2c06fed6549df8bc0eb4615b683749a4a92e1b" integrity sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA== dependencies: "@babel/types" "^7.20.7" "@types/estree@^1.0.6": version "1.0.6" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== "@types/graceful-fs@^4.1.3": version "4.1.9" - resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== dependencies: "@types/node" "*" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": version "2.0.6" - resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== "@types/istanbul-lib-report@*": version "3.0.3" - resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": version "3.0.4" - resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== dependencies: "@types/istanbul-lib-report" "*" "@types/jest@^29.4.0": version "29.5.11" - resolved "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.11.tgz#0c13aa0da7d0929f078ab080ae5d4ced80fa2f2c" integrity sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ== dependencies: expect "^29.0.0" @@ -962,43 +962,50 @@ "@types/json-schema@^7.0.15": version "7.0.15" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/node@*", "@types/node@^20.17.6": +"@types/node@*": + version "20.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" + integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== + dependencies: + undici-types "~5.26.4" + +"@types/node@^20.17.6": version "20.19.11" - resolved "https://registry.npmjs.org/@types/node/-/node-20.19.11.tgz" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.11.tgz#728cab53092bd5f143beed7fbba7ba99de3c16c4" integrity sha512-uug3FEEGv0r+jrecvUUpbY8lLisvIjg6AAic6a2bSP5OEOLeJsDSnvhCDov7ipFFMXS3orMpzlmi0ZcuGkBbow== dependencies: undici-types "~6.21.0" "@types/stack-utils@^2.0.0": version "2.0.3" - resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== "@types/ws@^8.5.13": version "8.5.14" - resolved "https://registry.npmjs.org/@types/ws/-/ws-8.5.14.tgz" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.14.tgz#93d44b268c9127d96026cf44353725dd9b6c3c21" integrity sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw== dependencies: "@types/node" "*" "@types/yargs-parser@*": version "21.0.3" - resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== "@types/yargs@^17.0.8": version "17.0.32" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== dependencies: "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.31.1.tgz#62f1befe59647524994e89de4516d8dcba7a850a" integrity sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ== dependencies: "@eslint-community/regexpp" "^4.10.0" @@ -1013,7 +1020,7 @@ "@typescript-eslint/parser@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.31.1.tgz#e9b0ccf30d37dde724ee4d15f4dbc195995cce1b" integrity sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q== dependencies: "@typescript-eslint/scope-manager" "8.31.1" @@ -1024,7 +1031,7 @@ "@typescript-eslint/scope-manager@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.31.1.tgz#1eb52e76878f545e4add142e0d8e3e97e7aa443b" integrity sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw== dependencies: "@typescript-eslint/types" "8.31.1" @@ -1032,7 +1039,7 @@ "@typescript-eslint/type-utils@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.31.1.tgz#be0f438fb24b03568e282a0aed85f776409f970c" integrity sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA== dependencies: "@typescript-eslint/typescript-estree" "8.31.1" @@ -1042,12 +1049,12 @@ "@typescript-eslint/types@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.31.1.tgz#478ed6f7e8aee1be7b63a60212b6bffe1423b5d4" integrity sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ== "@typescript-eslint/typescript-estree@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.31.1.tgz#37792fe7ef4d3021c7580067c8f1ae66daabacdf" integrity sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag== dependencies: "@typescript-eslint/types" "8.31.1" @@ -1061,7 +1068,7 @@ "@typescript-eslint/utils@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.31.1.tgz#5628ea0393598a0b2f143d0fc6d019f0dee9dd14" integrity sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" @@ -1071,7 +1078,7 @@ "@typescript-eslint/visitor-keys@8.31.1": version "8.31.1" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.31.1.tgz#6742b0e3ba1e0c1e35bdaf78c03e759eb8dd8e75" integrity sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw== dependencies: "@typescript-eslint/types" "8.31.1" @@ -1079,22 +1086,27 @@ acorn-jsx@^5.3.2: version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: version "8.2.0" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.14.0, acorn@^8.4.1: +acorn@^8.14.0: version "8.14.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.4.1: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + aggregate-error@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== dependencies: clean-stack "^2.0.0" @@ -1102,7 +1114,7 @@ aggregate-error@^3.0.0: ajv@^6.12.4: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -1112,55 +1124,55 @@ ajv@^6.12.4: ansi-escapes@^4.2.1: version "4.3.2" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + 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-escapes@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.0.0.tgz#00fc19f491bbb18e1d481b97868204f92109bfe7" integrity sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw== dependencies: environment "^1.0.0" ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" ansi-styles@^5.0.0: version "5.2.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== any-promise@^1.0.0: version "1.3.0" - resolved "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A== anymatch@^3.0.3: version "3.1.3" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" @@ -1168,24 +1180,24 @@ anymatch@^3.0.3: arg@^4.1.0: version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== babel-jest@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== dependencies: "@jest/transform" "^29.7.0" @@ -1198,7 +1210,7 @@ babel-jest@^29.7.0: babel-plugin-istanbul@^6.1.1: version "6.1.1" - resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -1209,7 +1221,7 @@ babel-plugin-istanbul@^6.1.1: babel-plugin-jest-hoist@^29.6.3: version "29.6.3" - resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== dependencies: "@babel/template" "^7.3.3" @@ -1219,7 +1231,7 @@ babel-plugin-jest-hoist@^29.6.3: babel-preset-current-node-syntax@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" @@ -1237,7 +1249,7 @@ babel-preset-current-node-syntax@^1.0.0: babel-preset-jest@^29.6.3: version "29.6.3" - resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== dependencies: babel-plugin-jest-hoist "^29.6.3" @@ -1245,12 +1257,12 @@ babel-preset-jest@^29.6.3: balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -1258,21 +1270,21 @@ brace-expansion@^1.1.7: brace-expansion@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== dependencies: balanced-match "^1.0.0" braces@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== dependencies: fill-range "^7.1.1" browserslist@^4.22.2: version "4.22.2" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== dependencies: caniuse-lite "^1.0.30001565" @@ -1282,46 +1294,46 @@ browserslist@^4.22.2: bs-logger@0.x: version "0.2.6" - resolved "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== dependencies: fast-json-stable-stringify "2.x" bser@2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: node-int64 "^0.4.0" buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelcase@^6.2.0: version "6.3.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001565: version "1.0.30001570" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz#b4e5c1fa786f733ab78fc70f592df6b3f23244ca" integrity sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw== chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -1330,7 +1342,7 @@ chalk@^2.4.2: chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -1338,32 +1350,37 @@ chalk@^4.0.0, chalk@^4.1.2: chalk@^5.3.0: version "5.3.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== char-regex@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== ci-info@^3.2.0: version "3.9.0" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== -cjs-module-lexer@^1.0.0, cjs-module-lexer@^1.2.3: +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + +cjs-module-lexer@^1.2.3: version "1.4.1" - resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz#707413784dbb3a72aa11c2f2b042a0bef4004170" integrity sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA== clean-stack@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== cli-highlight@^2.1.11: version "2.1.11" - resolved "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz" + resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf" integrity sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg== dependencies: chalk "^4.0.0" @@ -1375,7 +1392,7 @@ cli-highlight@^2.1.11: cli-table3@^0.6.3, cli-table3@^0.6.5: version "0.6.5" - resolved "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.5.tgz#013b91351762739c16a9567c21a04632e449bf2f" integrity sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ== dependencies: string-width "^4.2.0" @@ -1384,7 +1401,7 @@ cli-table3@^0.6.3, cli-table3@^0.6.5: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" @@ -1393,7 +1410,7 @@ cliui@^7.0.2: cliui@^8.0.1: version "8.0.1" - resolved "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== dependencies: string-width "^4.2.0" @@ -1402,56 +1419,56 @@ cliui@^8.0.1: co@^4.6.0: version "4.6.0" - resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== collect-v8-coverage@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== commander@^10.0.1: version "10.0.1" - resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== convert-source-map@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== create-jest@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== dependencies: "@jest/types" "^29.6.3" @@ -1464,12 +1481,12 @@ create-jest@^29.7.0: create-require@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== dependencies: path-key "^3.1.0" @@ -1478,108 +1495,108 @@ cross-spawn@^7.0.3, cross-spawn@^7.0.6: debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2: version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" debug@^4.3.4, debug@^4.3.7: version "4.3.7" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: ms "^2.1.3" dedent@^1.0.0: version "1.5.1" - resolved "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deep-object-diff@^1.1.9: version "1.1.9" - resolved "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz" + resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.9.tgz#6df7ef035ad6a0caa44479c536ed7b02570f4595" integrity sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA== deepmerge@^4.2.2: version "4.3.1" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== detect-newline@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== diff-sequences@^29.6.3: version "29.6.3" - resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== diff@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== electron-to-chromium@^1.4.601: version "1.4.614" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.614.tgz#2fe789d61fa09cb875569f37c309d0c2701f91c0" integrity sha512-X4ze/9Sc3QWs6h92yerwqv7aB/uU8vCjZcrMjA8N9R1pjMFRe44dLsck5FzLilOYvcXuDn93B+bpGYyufc70gQ== emittery@^0.13.1: version "0.13.1" - resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== emojilib@^2.4.0: version "2.4.0" - resolved "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz" + resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e" integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw== environment@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/environment/-/environment-1.1.0.tgz#8e86c66b180f363c7ab311787e0259665f45a9f1" integrity sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q== error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== eslint-plugin-prettier@^5.4.1: version "5.4.1" - resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz#99b55d7dd70047886b2222fdd853665f180b36af" integrity sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg== dependencies: prettier-linter-helpers "^1.0.0" @@ -1587,12 +1604,12 @@ eslint-plugin-prettier@^5.4.1: eslint-plugin-unused-imports@^4.1.4: version "4.1.4" - resolved "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.1.4.tgz#62ddc7446ccbf9aa7b6f1f0b00a980423cda2738" integrity sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ== eslint-scope@^8.2.0: version "8.2.0" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== dependencies: esrecurse "^4.3.0" @@ -1600,17 +1617,17 @@ eslint-scope@^8.2.0: eslint-visitor-keys@^3.3.0: version "3.4.3" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== eslint-visitor-keys@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== eslint@^9.20.1: version "9.20.1" - resolved "https://registry.npmjs.org/eslint/-/eslint-9.20.1.tgz" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.20.1.tgz#923924c078f5226832449bac86662dd7e53c91d6" integrity sha512-m1mM33o6dBUjxl2qb6wv6nGNwCAsns1eKtaQ4l/NPHeTvhiUPbtdfMyktxN4B3fgHIgsYh1VT3V9txblpQHq+g== dependencies: "@eslint-community/eslint-utils" "^4.2.0" @@ -1650,7 +1667,7 @@ eslint@^9.20.1: espree@^10.0.1, espree@^10.3.0: version "10.3.0" - resolved "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== dependencies: acorn "^8.14.0" @@ -1659,36 +1676,36 @@ espree@^10.0.1, espree@^10.3.0: esprima@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.5.0: version "1.6.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== execa@^5.0.0, execa@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" @@ -1703,12 +1720,12 @@ execa@^5.0.0, execa@^5.1.1: exit@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== expect@^29.0.0, expect@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== dependencies: "@jest/expect-utils" "^29.7.0" @@ -1719,24 +1736,24 @@ expect@^29.0.0, expect@^29.7.0: fast-check@^3.22.0: version "3.23.2" - resolved "https://registry.npmjs.org/fast-check/-/fast-check-3.23.2.tgz" + resolved "https://registry.yarnpkg.com/fast-check/-/fast-check-3.23.2.tgz#0129f1eb7e4f500f58e8290edc83c670e4a574a2" integrity sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A== dependencies: pure-rand "^6.1.0" fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2: version "1.3.0" - resolved "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.3.2: version "3.3.2" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -1747,50 +1764,50 @@ fast-glob@^3.3.2: fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: version "1.17.1" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== dependencies: reusify "^1.0.4" fb-watchman@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" fflate@^0.8.2: version "0.8.2" - resolved "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== file-entry-cache@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: flat-cache "^4.0.0" fill-range@^7.1.1: version "7.1.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== dependencies: to-regex-range "^5.0.1" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -1798,7 +1815,7 @@ find-up@^4.0.0, find-up@^4.1.0: find-up@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" @@ -1806,7 +1823,7 @@ find-up@^5.0.0: flat-cache@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" @@ -1814,12 +1831,12 @@ flat-cache@^4.0.0: flatted@^3.2.9: version "3.3.2" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.2.tgz#adba1448a9841bec72b42c532ea23dbbedef1a27" integrity sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.3.2: @@ -1829,51 +1846,51 @@ fsevents@^2.3.2: function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== get-stdin@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== get-stream@^6.0.0: version "6.0.1" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== glob-parent@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.2: version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" glob@^7.1.3, glob@^7.1.4: version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1885,7 +1902,7 @@ glob@^7.1.3, glob@^7.1.4: glob@^8.0.1: version "8.1.0" - resolved "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz" + resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== dependencies: fs.realpath "^1.0.0" @@ -1896,78 +1913,78 @@ glob@^8.0.1: globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^14.0.0: version "14.0.0" - resolved "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== graceful-fs@^4.2.9: version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphemer@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== hasown@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== dependencies: function-bind "^1.1.2" highlight.js@^10.7.1: version "10.7.3" - resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== human-signals@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== iconv-lite@^0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" ignore-walk@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776" integrity sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw== dependencies: minimatch "^5.0.1" ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -1975,7 +1992,7 @@ import-fresh@^3.2.1: import-local@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" @@ -1983,17 +2000,17 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -2001,39 +2018,39 @@ inflight@^1.0.4: inherits@2, inherits@^2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-core-module@^2.13.0: version "2.13.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: hasown "^2.0.0" is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-generator-fn@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" @@ -2045,27 +2062,27 @@ is-node-process@^1.2.0: is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: version "3.2.2" - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== istanbul-lib-instrument@^5.0.4: version "5.2.1" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: "@babel/core" "^7.12.3" @@ -2076,7 +2093,7 @@ istanbul-lib-instrument@^5.0.4: istanbul-lib-instrument@^6.0.0: version "6.0.1" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== dependencies: "@babel/core" "^7.12.3" @@ -2087,7 +2104,7 @@ istanbul-lib-instrument@^6.0.0: istanbul-lib-report@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== dependencies: istanbul-lib-coverage "^3.0.0" @@ -2096,7 +2113,7 @@ istanbul-lib-report@^3.0.0: istanbul-lib-source-maps@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: debug "^4.1.1" @@ -2105,7 +2122,7 @@ istanbul-lib-source-maps@^4.0.0: istanbul-reports@^3.1.3: version "3.1.6" - resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== dependencies: html-escaper "^2.0.0" @@ -2113,7 +2130,7 @@ istanbul-reports@^3.1.3: jest-changed-files@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== dependencies: execa "^5.0.0" @@ -2122,7 +2139,7 @@ jest-changed-files@^29.7.0: jest-circus@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== dependencies: "@jest/environment" "^29.7.0" @@ -2148,7 +2165,7 @@ jest-circus@^29.7.0: jest-cli@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== dependencies: "@jest/core" "^29.7.0" @@ -2165,7 +2182,7 @@ jest-cli@^29.7.0: jest-config@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== dependencies: "@babel/core" "^7.11.6" @@ -2193,7 +2210,7 @@ jest-config@^29.7.0: jest-diff@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== dependencies: chalk "^4.0.0" @@ -2203,14 +2220,14 @@ jest-diff@^29.7.0: jest-docblock@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== dependencies: detect-newline "^3.0.0" jest-each@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== dependencies: "@jest/types" "^29.6.3" @@ -2221,7 +2238,7 @@ jest-each@^29.7.0: jest-environment-node@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== dependencies: "@jest/environment" "^29.7.0" @@ -2233,12 +2250,12 @@ jest-environment-node@^29.7.0: jest-get-type@^29.6.3: version "29.6.3" - resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== jest-haste-map@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== dependencies: "@jest/types" "^29.6.3" @@ -2257,7 +2274,7 @@ jest-haste-map@^29.7.0: jest-leak-detector@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== dependencies: jest-get-type "^29.6.3" @@ -2265,7 +2282,7 @@ jest-leak-detector@^29.7.0: jest-matcher-utils@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== dependencies: chalk "^4.0.0" @@ -2275,7 +2292,7 @@ jest-matcher-utils@^29.7.0: jest-message-util@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== dependencies: "@babel/code-frame" "^7.12.13" @@ -2290,7 +2307,7 @@ jest-message-util@^29.7.0: jest-mock@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== dependencies: "@jest/types" "^29.6.3" @@ -2299,17 +2316,17 @@ jest-mock@^29.7.0: jest-pnp-resolver@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== jest-regex-util@^29.6.3: version "29.6.3" - resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== jest-resolve-dependencies@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== dependencies: jest-regex-util "^29.6.3" @@ -2317,7 +2334,7 @@ jest-resolve-dependencies@^29.7.0: jest-resolve@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== dependencies: chalk "^4.0.0" @@ -2332,7 +2349,7 @@ jest-resolve@^29.7.0: jest-runner@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== dependencies: "@jest/console" "^29.7.0" @@ -2359,7 +2376,7 @@ jest-runner@^29.7.0: jest-runtime@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== dependencies: "@jest/environment" "^29.7.0" @@ -2387,7 +2404,7 @@ jest-runtime@^29.7.0: jest-snapshot@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== dependencies: "@babel/core" "^7.11.6" @@ -2413,7 +2430,7 @@ jest-snapshot@^29.7.0: jest-util@^29.0.0, jest-util@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== dependencies: "@jest/types" "^29.6.3" @@ -2425,7 +2442,7 @@ jest-util@^29.0.0, jest-util@^29.7.0: jest-validate@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== dependencies: "@jest/types" "^29.6.3" @@ -2437,7 +2454,7 @@ jest-validate@^29.7.0: jest-watcher@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== dependencies: "@jest/test-result" "^29.7.0" @@ -2451,7 +2468,7 @@ jest-watcher@^29.7.0: jest-worker@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== dependencies: "@types/node" "*" @@ -2461,7 +2478,7 @@ jest-worker@^29.7.0: jest@^29.4.0: version "29.7.0" - resolved "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: "@jest/core" "^29.7.0" @@ -2471,12 +2488,12 @@ jest@^29.4.0: js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" @@ -2484,27 +2501,27 @@ js-yaml@^3.13.1: js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== json-buffer@3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== -json-schema-to-ts@3.1.1: +json-schema-to-ts@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz#81f3acaf5a34736492f6f5f51870ef9ece1ca853" integrity sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g== @@ -2514,12 +2531,12 @@ json-schema-to-ts@3.1.1: json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stringify-safe@^5.0.1: @@ -2529,34 +2546,34 @@ json-stringify-safe@^5.0.1: json5@^2.2.2, json5@^2.2.3: version "2.2.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonc-parser@^3.2.0: version "3.2.1" - resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== keyv@^4.5.4: version "4.5.4" - resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== dependencies: json-buffer "3.0.1" kleur@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== leven@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== levn@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" @@ -2564,74 +2581,74 @@ levn@^0.4.1: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" lodash.memoize@4.x: version "4.1.2" - resolved "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lru-cache@^10.4.3: version "10.4.3" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" make-dir@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== dependencies: semver "^7.5.3" make-error@1.x, make-error@^1.1.1: version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== makeerror@1.0.12: version "1.0.12" - resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: tmpl "1.0.5" marked-terminal@^7.1.0: version "7.2.1" - resolved "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.2.1.tgz" + resolved "https://registry.yarnpkg.com/marked-terminal/-/marked-terminal-7.2.1.tgz#9c1ae073a245a03c6a13e3eeac6f586f29856068" integrity sha512-rQ1MoMFXZICWNsKMiiHwP/Z+92PLKskTPXj+e7uwXmuMPkNn7iTqC+IvDekVm1MPeC9wYQeLxeFaOvudRR/XbQ== dependencies: ansi-escapes "^7.0.0" @@ -2644,22 +2661,22 @@ marked-terminal@^7.1.0: marked@^9.1.2: version "9.1.6" - resolved "https://registry.npmjs.org/marked/-/marked-9.1.6.tgz" + resolved "https://registry.yarnpkg.com/marked/-/marked-9.1.6.tgz#5d2a3f8180abfbc5d62e3258a38a1c19c0381695" integrity sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q== merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== merge2@^1.3.0: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: version "4.0.8" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" @@ -2667,53 +2684,53 @@ micromatch@^4.0.4: mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" minimatch@^5.0.1: version "5.1.6" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== dependencies: brace-expansion "^2.0.1" minimatch@^9.0.4: version "9.0.5" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" minimist@^1.2.6: version "1.2.6" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== mri@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ms@^2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== mz@^2.4.0: version "2.7.0" - resolved "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== dependencies: any-promise "^1.0.0" @@ -2722,7 +2739,7 @@ mz@^2.4.0: natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== nock@^14.0.10: @@ -2736,7 +2753,7 @@ nock@^14.0.10: node-emoji@^2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-2.1.3.tgz#93cfabb5cc7c3653aa52f29d6ffb7927d8047c06" integrity sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA== dependencies: "@sindresorhus/is" "^4.6.0" @@ -2746,34 +2763,34 @@ node-emoji@^2.1.3: node-int64@^0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-releases@^2.0.14: version "2.0.14" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== normalize-path@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== npm-bundled@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-2.0.1.tgz#94113f7eb342cd7a67de1e789f896b04d2c600f4" integrity sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw== dependencies: npm-normalize-package-bin "^2.0.0" npm-normalize-package-bin@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz#9447a1adaaf89d8ad0abe24c6c84ad614a675fff" integrity sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ== npm-packlist@^5.1.3: version "5.1.3" - resolved "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.3.tgz#69d253e6fd664b9058b85005905012e00e69274b" integrity sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg== dependencies: glob "^8.0.1" @@ -2783,33 +2800,33 @@ npm-packlist@^5.1.3: npm-run-path@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" object-assign@^4.0.1: version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== once@^1.3.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" onetime@^5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" optionator@^0.9.3: version "0.9.3" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== dependencies: "@aashutoshrathi/word-wrap" "^1.2.3" @@ -2826,61 +2843,61 @@ outvariant@^1.4.0, outvariant@^1.4.3: p-all@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/p-all/-/p-all-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-all/-/p-all-3.0.0.tgz#077c023c37e75e760193badab2bad3ccd5782bfb" integrity sha512-qUZbvbBFVXm6uJ7U/WDiO0fv6waBMbjlCm4E66oZdRR+egswICarIdHyVSZZHudH8T5SF8x/JG0q0duFzPnlBw== dependencies: p-map "^4.0.0" p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" p-map@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-json@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -2890,83 +2907,88 @@ parse-json@^5.2.0: parse5-htmlparser2-tree-adapter@^6.0.0: version "6.0.1" - resolved "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== dependencies: parse5 "^6.0.1" parse5@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== parse5@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -picocolors@^1.0.0, picocolors@^1.1.1: +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picocolors@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pirates@^4.0.4: version "4.0.6" - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== dependencies: fast-diff "^1.1.2" prettier@^3.0.0: version "3.1.1" - resolved "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== dependencies: "@jest/schemas" "^29.6.3" @@ -2975,7 +2997,7 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: prompts@^2.0.1: version "2.4.2" - resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== dependencies: kleur "^3.0.3" @@ -2988,7 +3010,7 @@ propagate@^2.0.0: publint@^0.2.12: version "0.2.12" - resolved "https://registry.npmjs.org/publint/-/publint-0.2.12.tgz" + resolved "https://registry.yarnpkg.com/publint/-/publint-0.2.12.tgz#d25cd6bd243d5bdd640344ecdddb3eeafdcc4059" integrity sha512-YNeUtCVeM4j9nDiTT2OPczmlyzOkIXNtdDZnSuajAxS/nZ6j3t7Vs9SUB4euQNddiltIwu7Tdd3s+hr08fAsMw== dependencies: npm-packlist "^5.1.3" @@ -2997,27 +3019,32 @@ publint@^0.2.12: punycode@^2.1.0: version "2.3.0" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -pure-rand@^6.0.0, pure-rand@^6.1.0: +pure-rand@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" + integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== + +pure-rand@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== react-is@^18.0.0: version "18.2.0" - resolved "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== readable-stream@^3.4.0: version "3.6.2" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== dependencies: inherits "^2.0.3" @@ -3026,34 +3053,34 @@ readable-stream@^3.4.0: require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve.exports@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== resolve@^1.20.0: version "1.22.8" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: is-core-module "^2.13.0" @@ -3062,92 +3089,92 @@ resolve@^1.20.0: reusify@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" sade@^1.8.1: version "1.8.1" - resolved "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== dependencies: mri "^1.1.0" safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== semver@^6.3.0, semver@^6.3.1: version "6.3.1" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.5.3: version "7.5.4" - resolved "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== dependencies: lru-cache "^6.0.0" semver@^7.5.4: version "7.6.3" - resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== semver@^7.6.0: version "7.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== sisteransi@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== skin-tone@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/skin-tone/-/skin-tone-2.0.0.tgz#4e3933ab45c0d4f4f781745d64b9f4c208e41237" integrity sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA== dependencies: unicode-emoji-modifier-base "^1.0.0" slash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== source-map-support@0.5.13: version "0.5.13" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== dependencies: buffer-from "^1.0.0" @@ -3155,17 +3182,17 @@ source-map-support@0.5.13: source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stack-utils@^2.0.3: version "2.0.6" - resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" @@ -3177,7 +3204,7 @@ strict-event-emitter@^0.5.1: string-length@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== dependencies: char-regex "^1.0.2" @@ -3185,14 +3212,14 @@ string-length@^4.0.1: string-to-stream@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/string-to-stream/-/string-to-stream-3.0.1.tgz#480e6fb4d5476d31cb2221f75307a5dcb6638a42" integrity sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg== dependencies: readable-stream "^3.4.0" string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" @@ -3201,67 +3228,67 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== superstruct@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/superstruct/-/superstruct-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" integrity sha512-7JpaAoX2NGyoFlI9NBh66BQXGONc+uE+MRS5i2iOBKuS4e+ccgMDjATgZldkah+33DakBxDHiss9kvUcGAO8UQ== supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-color@^8.0.0: version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-hyperlinks@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz#b56150ff0173baacc15f21956450b61f2b18d3ac" integrity sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A== dependencies: has-flag "^4.0.0" @@ -3269,19 +3296,19 @@ supports-hyperlinks@^3.1.0: supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== synckit@^0.11.7: version "0.11.8" - resolved "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.8.tgz#b2aaae998a4ef47ded60773ad06e7cb821f55457" integrity sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A== dependencies: "@pkgr/core" "^0.2.4" test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: "@istanbuljs/schema" "^0.1.2" @@ -3290,48 +3317,48 @@ test-exclude@^6.0.0: thenify-all@^1.0.0: version "1.6.0" - resolved "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA== dependencies: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": version "3.3.1" - resolved "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== dependencies: any-promise "^1.0.0" tmpl@1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" ts-algebra@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/ts-algebra/-/ts-algebra-2.0.0.tgz#4e3e0953878f26518fce7f6bb115064a65388b7a" integrity sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw== ts-api-utils@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== ts-jest@^29.1.0: version "29.1.1" - resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.1.tgz#f58fe62c63caf7bfcc5cc6472082f79180f0815b" integrity sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA== dependencies: bs-logger "0.x" @@ -3345,7 +3372,7 @@ ts-jest@^29.1.0: ts-node@^10.5.0: version "10.7.0" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== dependencies: "@cspotcode/source-map-support" "0.7.0" @@ -3364,8 +3391,7 @@ ts-node@^10.5.0: "tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz" - integrity sha512-tWyCXnx0WqCkVlo5s+4KMj7HC0/0YrCZY0PustUwX9F2lNwd8Kp07q/Q56uGvV9q80XaSDrhy0YqBmrX5TDNpQ== + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" dependencies: debug "^4.3.7" fast-glob "^3.3.2" @@ -3380,7 +3406,7 @@ ts-node@^10.5.0: tsconfig-paths@^4.0.0: version "4.2.0" - resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== dependencies: json5 "^2.2.2" @@ -3389,29 +3415,29 @@ tsconfig-paths@^4.0.0: tslib@^2.8.1: version "2.8.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-detect@4.0.8: version "4.0.8" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== typescript-eslint@8.31.1: version "8.31.1" - resolved "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.31.1.tgz" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.31.1.tgz#b77ab1e48ced2daab9225ff94bab54391a4af69b" integrity sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA== dependencies: "@typescript-eslint/eslint-plugin" "8.31.1" @@ -3420,27 +3446,32 @@ typescript-eslint@8.31.1: typescript@5.6.1-rc: version "5.6.1-rc" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.6.1-rc.tgz" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.6.1-rc.tgz#d5e4d7d8170174fed607b74cc32aba3d77018e02" integrity sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ== typescript@5.8.3: version "5.8.3" - resolved "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== +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== + undici-types@~6.21.0: version "6.21.0" - resolved "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== unicode-emoji-modifier-base@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459" integrity sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g== update-browserslist-db@^1.0.13: version "1.0.13" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== dependencies: escalade "^3.1.1" @@ -3448,24 +3479,24 @@ update-browserslist-db@^1.0.13: uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" util-deprecate@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== v8-compile-cache-lib@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== v8-to-istanbul@^9.0.1: version "9.2.0" - resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== dependencies: "@jridgewell/trace-mapping" "^0.3.12" @@ -3474,26 +3505,26 @@ v8-to-istanbul@^9.0.1: validate-npm-package-name@^5.0.0: version "5.0.1" - resolved "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz#a316573e9b49f3ccd90dbb6eb52b3f06c6d604e8" integrity sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ== walker@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: makeerror "1.0.12" which@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -3502,12 +3533,12 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== dependencies: imurmurhash "^0.1.4" @@ -3515,37 +3546,37 @@ write-file-atomic@^4.0.2: ws@^8.18.0: version "8.18.0" - resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^3.0.2: version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yargs-parser@^20.2.2: version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== yargs-parser@^21.0.1, yargs-parser@^21.1.1: version "21.1.1" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== yargs@^16.0.0: version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -3558,7 +3589,7 @@ yargs@^16.0.0: yargs@^17.3.1, yargs@^17.7.2: version "17.7.2" - resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== dependencies: cliui "^8.0.1" @@ -3571,15 +3602,15 @@ yargs@^17.3.1, yargs@^17.7.2: yn@3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== "zod@^3.25 || ^4.0": version "4.1.11" - resolved "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.11.tgz#4aab62f76cfd45e6c6166519ba31b2ea019f75f5" integrity sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg== From afb98d2712ed5e186eab0cf30c4c31874c5dd40f Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 12:05:19 -0500 Subject: [PATCH 23/43] don't await the promise --- src/lib/beta/BetaToolRunner.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 2dc8141f4..e51f088d7 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -147,8 +147,7 @@ export class BetaToolRunner { this.#options, ); - this.#message = this.#chatCompletion.then((resp) => resp.choices.at(0)!.message); - await this.#message; // TODO: we would like to not need to await it + this.#message = this.#chatCompletion.then((resp) => resp.choices.at(0)!.message).catch(() => {}); yield this.#chatCompletion as any; } From 4c95b49f99ad56e2a1c88ddbf84c2ca8d7b6f5db Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 12:08:21 -0500 Subject: [PATCH 24/43] use zod v4 --- src/helpers/beta/zod.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 3307df9ed..8c8d60cd6 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -1,5 +1,5 @@ -import type { infer as zodInfer, ZodType } from 'zod'; -import * as z from 'zod'; +import type { infer as zodInfer, ZodType } from 'zod/v4'; +import * as z from 'zod/v4'; import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; import type { FunctionTool } from '../../resources/beta'; From 5b52aa9c17a74dcfdb9491fbf96104da8dc1f0d5 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 12:12:18 -0500 Subject: [PATCH 25/43] catch with separate update --- src/lib/beta/BetaToolRunner.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index e51f088d7..1bd078506 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -147,7 +147,8 @@ export class BetaToolRunner { this.#options, ); - this.#message = this.#chatCompletion.then((resp) => resp.choices.at(0)!.message).catch(() => {}); + this.#message = this.#chatCompletion.then((resp) => resp.choices.at(0)!.message); + this.#message.catch(() => {}); yield this.#chatCompletion as any; } From cdeb4e6117057781a2fa60dfc8a17280031e2f72 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 15:42:25 -0500 Subject: [PATCH 26/43] PR feedback --- examples/tool-calls-beta-zod.ts | 6 +- examples/tool-helpers-advanced-streaming.ts | 6 +- examples/tool-helpers-advanced.ts | 2 +- src/helpers/beta/zod.ts | 6 +- src/lib/beta/BetaToolRunner.ts | 57 +++++++++---------- src/resources/beta/chat.ts | 3 +- ...lRunner.test.ts => BetaToolRunner.test.ts} | 4 +- ...rE2E.test.ts => BetaToolRunnerE2E.test.ts} | 6 +- 8 files changed, 42 insertions(+), 48 deletions(-) rename tests/lib/tools/{ToolRunner.test.ts => BetaToolRunner.test.ts} (99%) rename tests/lib/tools/{ToolRunnerE2E.test.ts => BetaToolRunnerE2E.test.ts} (98%) diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts index 18316b102..80c5192cc 100755 --- a/examples/tool-calls-beta-zod.ts +++ b/examples/tool-calls-beta-zod.ts @@ -18,7 +18,7 @@ async function main() { betaZodTool({ name: 'getWeather', description: 'Get the weather at a specific location', - inputSchema: z.object({ + parameters: z.object({ location: z.string().describe('The city and state, e.g. San Francisco, CA'), }), run: ({ location }) => { @@ -28,7 +28,7 @@ async function main() { betaZodTool({ name: 'getTime', description: 'Get the current time in a specific timezone', - inputSchema: z.object({ + parameters: z.object({ timezone: z.string().describe('The timezone, e.g. America/Los_Angeles'), }), run: ({ timezone }) => { @@ -38,7 +38,7 @@ async function main() { betaZodTool({ name: 'getCurrencyExchangeRate', description: 'Get the exchange rate between two currencies', - inputSchema: z.object({ + parameters: z.object({ from_currency: z.string().describe('The currency to convert from, e.g. USD'), to_currency: z.string().describe('The currency to convert to, e.g. EUR'), }), diff --git a/examples/tool-helpers-advanced-streaming.ts b/examples/tool-helpers-advanced-streaming.ts index aa28afd65..12770331e 100755 --- a/examples/tool-helpers-advanced-streaming.ts +++ b/examples/tool-helpers-advanced-streaming.ts @@ -18,7 +18,7 @@ async function main() { betaZodTool({ name: 'getWeather', description: 'Get the weather at a specific location', - inputSchema: z.object({ + parameters: z.object({ location: z.string().describe('The city and state, e.g. San Francisco, CA'), }), run: ({ location }) => { @@ -28,7 +28,7 @@ async function main() { betaZodTool({ name: 'getTime', description: 'Get the current time in a specific timezone', - inputSchema: z.object({ + parameters: z.object({ timezone: z.string().describe('The timezone, e.g. America/Los_Angeles'), }), run: ({ timezone }) => { @@ -38,7 +38,7 @@ async function main() { betaZodTool({ name: 'getCurrencyExchangeRate', description: 'Get the exchange rate between two currencies', - inputSchema: z.object({ + parameters: z.object({ from_currency: z.string().describe('The currency to convert from, e.g. USD'), to_currency: z.string().describe('The currency to convert to, e.g. EUR'), }), diff --git a/examples/tool-helpers-advanced.ts b/examples/tool-helpers-advanced.ts index eac810305..8875dcb6f 100755 --- a/examples/tool-helpers-advanced.ts +++ b/examples/tool-helpers-advanced.ts @@ -18,7 +18,7 @@ async function main() { betaZodTool({ name: 'getWeather', description: 'Get the weather at a specific location', - inputSchema: z.object({ + parameters: z.object({ location: z.string().describe('The city and state, e.g. San Francisco, CA'), }), run: ({ location }) => { diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 8c8d60cd6..8a5431e1c 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -11,11 +11,11 @@ import type { FunctionTool } from '../../resources/beta'; */ export function betaZodTool(options: { name: string; - inputSchema: InputSchema; + parameters: InputSchema; description: string; run: (args: zodInfer) => Promisable>; // TODO: I changed this but double check }): BetaRunnableTool> { - const jsonSchema = z.toJSONSchema(options.inputSchema, { reused: 'ref' }); + const jsonSchema = z.toJSONSchema(options.parameters, { reused: 'ref' }); if (jsonSchema.type !== 'object') { throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`); @@ -35,6 +35,6 @@ export function betaZodTool(options: { }, }, run: options.run, - parse: (args: unknown) => options.inputSchema.parse(args) as zodInfer, + parse: (args: unknown) => options.parameters.parse(args), }; } diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 1bd078506..9cab239b2 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -31,12 +31,14 @@ function promiseWithResolvers(): { } /** - * A ToolRunner handles the automatic conversation loop between the assistant and tools. + * A BetaToolRunner handles the automatic conversation loop between the assistant and tools. * - * A ToolRunner is an async iterable that yields either BetaMessage or BetaMessageStream objects - * depending on the streaming configuration. + * A BetaToolRunner is an async iterable that yields either ChatCompletion or + * ChatCompletionStream objects depending on the streaming configuration. */ -export class BetaToolRunner { +export class BetaToolRunner + implements AsyncIterable +{ /** Whether the async iterator has been consumed */ #consumed = false; /** Whether parameters have been mutated since the last API call */ @@ -72,8 +74,7 @@ export class BetaToolRunner { params: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions, ) { - params.n ??= 1; - if (params && params.n > 1) { + if (params.n && params.n > 1) { throw new Error('BetaToolRunner does not support n > 1'); } @@ -97,7 +98,7 @@ export class BetaToolRunner { async *[Symbol.asyncIterator](): AsyncIterator< Stream extends true ? ChatCompletionStream // TODO: for now! - : ChatCompletion | undefined + : ChatCompletion > { if (this.#consumed) { throw new OpenAIError('Cannot iterate over a consumed stream'); @@ -123,12 +124,10 @@ export class BetaToolRunner { this.#toolResponse = undefined; this.#iterationCount++; - const { ...params } = this.#state.params; - const apiParams = { ...params }; - delete apiParams.max_iterations; // our own param + const { max_iterations, ...params } = this.#state.params; if (params.stream) { - stream = this.client.beta.chat.completions.stream({ ...apiParams, stream: true }, this.#options); + stream = this.client.chat.completions.stream({ ...params, stream: true }, this.#options); this.#message = stream.finalMessage(); // Make sure that this promise doesn't throw before we get the option to do something about it. @@ -136,13 +135,10 @@ export class BetaToolRunner { this.#message?.catch(() => {}); yield stream as any; } else { - this.#chatCompletion = this.client.beta.chat.completions.create( + this.#chatCompletion = this.client.chat.completions.create( { - ...apiParams, // spread and explicit so we get better types + ...params, // spread and explicit so we get better types stream: false, - tools: params.tools, - messages: params.messages, - model: params.model, }, this.#options, ); @@ -155,15 +151,8 @@ export class BetaToolRunner { const prevMessage = await this.#message; - if (!prevMessage) { - throw new OpenAIError('ToolRunner concluded without a message from the server'); - } - if (!this.#mutated) { - // TODO: what if it is empty? - if (prevMessage) { - this.#state.params.messages.push(prevMessage); - } + this.#state.params.messages.push(prevMessage); } const toolMessages = await this.#generateToolResponse(prevMessage); @@ -173,7 +162,6 @@ export class BetaToolRunner { } } - // TODO: make sure this is correct? if (!toolMessages && !this.#mutated) { break; } @@ -206,21 +194,28 @@ export class BetaToolRunner { * * @example * // Direct parameter update - * runner.setMessagesParams({ + * runner.setChatParams({ * model: 'gpt-4o', * max_tokens: 500, * }); * * @example * // Using a mutator function - * runner.setMessagesParams((params) => ({ + * runner.setChatParams((params) => ({ * ...params, * max_tokens: 100, * })); + * + * @example + * // Appending a user message + * runner.setChatParams((params) => ({ + * ...params, + * messages: [...params.messages, { role: 'user', content: 'What colour is the sky?' }], + * })); */ - setMessagesParams(params: BetaToolRunnerParams): void; - setMessagesParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void; - setMessagesParams( + setChatParams(params: BetaToolRunnerParams): void; + setChatParams(mutator: (prevParams: BetaToolRunnerParams) => BetaToolRunnerParams): void; + setChatParams( paramsOrMutator: BetaToolRunnerParams | ((prevParams: BetaToolRunnerParams) => BetaToolRunnerParams), ) { if (typeof paramsOrMutator === 'function') { @@ -343,7 +338,7 @@ export class BetaToolRunner { * ); */ pushMessages(...messages: ChatCompletionMessageParam[]) { - this.setMessagesParams((params) => ({ + this.setChatParams((params) => ({ ...params, messages: [...params.messages, ...messages], })); diff --git a/src/resources/beta/chat.ts b/src/resources/beta/chat.ts index 86dd680b0..980884337 100644 --- a/src/resources/beta/chat.ts +++ b/src/resources/beta/chat.ts @@ -4,9 +4,8 @@ import { type BetaToolRunnerParams, type BetaToolRunnerRequestOptions, } from '../../lib/beta/BetaToolRunner'; -import { Chat as ChatResource } from '../../resources'; -export class BetaCompletions extends ChatResource.Completions { +export class BetaCompletions extends APIResource { toolRunner( body: BetaToolRunnerParams & { stream?: false }, options?: BetaToolRunnerRequestOptions, diff --git a/tests/lib/tools/ToolRunner.test.ts b/tests/lib/tools/BetaToolRunner.test.ts similarity index 99% rename from tests/lib/tools/ToolRunner.test.ts rename to tests/lib/tools/BetaToolRunner.test.ts index 4c7ef4dce..bd78b8c4e 100644 --- a/tests/lib/tools/ToolRunner.test.ts +++ b/tests/lib/tools/BetaToolRunner.test.ts @@ -942,7 +942,7 @@ describe('ToolRunner', () => { }); // Update parameters before iteration - runner.setMessagesParams({ + runner.setChatParams({ messages: [{ role: 'user', content: 'Updated message' }], model: 'gpt-4o', max_tokens: 200, @@ -981,7 +981,7 @@ describe('ToolRunner', () => { expect(toolResponse).toMatchObject([getWeatherToolResult('Paris')]); // Update params to append a custom tool_use block to messages - runner.setMessagesParams({ + runner.setChatParams({ ...runner.params, messages: [ ...runner.params.messages, diff --git a/tests/lib/tools/ToolRunnerE2E.test.ts b/tests/lib/tools/BetaToolRunnerE2E.test.ts similarity index 98% rename from tests/lib/tools/ToolRunnerE2E.test.ts rename to tests/lib/tools/BetaToolRunnerE2E.test.ts index cee2ca3b4..ee32ddc23 100644 --- a/tests/lib/tools/ToolRunnerE2E.test.ts +++ b/tests/lib/tools/BetaToolRunnerE2E.test.ts @@ -104,7 +104,7 @@ describe('toolRunner integration tests', () => { ) { return betaZodTool({ name: 'test_tool', - inputSchema: z.object({ value: z.string() }), + parameters: z.object({ value: z.string() }), description: 'A test tool', run: () => 'Tool result', ...customConfig, @@ -114,7 +114,7 @@ describe('toolRunner integration tests', () => { function createCounterTool() { return betaZodTool({ name: 'test_tool', - inputSchema: z.object({ count: z.number() }), + parameters: z.object({ count: z.number() }), description: 'A test tool', run: (args) => `Called with ${args.count}`, }); @@ -259,7 +259,7 @@ describe('toolRunner integration tests', () => { }); // Update parameters - runner.setMessagesParams({ + runner.setChatParams({ model: 'gpt-4o', max_tokens: 500, messages: [{ role: 'user', content: 'Updated message' }], From 3f96a58c06156b4b669d50c57b622bd1bd316be1 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 16:39:17 -0500 Subject: [PATCH 27/43] start working on docs --- README.md | 79 +++++++++++++ examples/tool-calls-beta-zod.ts | 8 +- examples/tool-helpers-advanced-streaming.ts | 8 +- examples/tool-helpers-advanced.ts | 4 +- helpers.md | 124 ++++++++++++++++++++ src/helpers/beta/zod.ts | 2 +- src/lib/beta/BetaToolRunner.ts | 2 +- tests/lib/tools/BetaToolRunnerE2E.test.ts | 6 +- 8 files changed, 218 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 351d9c0dc..b2b7c4020 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,85 @@ await client.files.create({ }); ``` +## Streaming Helpers + +```ts +import OpenAI from 'openai'; + +const client = new OpenAI(); + +async function main() { + const stream = client.chat.completions + .stream({ + model: 'gpt-4o', + max_tokens: 1024, + messages: [ + { + role: 'user', + content: 'Say hi!', + }, + ], + }) + .on('chunk', (text) => { + console.log(text); + }); + + const message = await stream.finalMessage(); + console.log(message); +} + +main(); +``` + +## Tool Helpers + +The SDK makes it easy to create and run [function tools with the chats API](https://platform.openai.com/docs/guides/function-calling). You can use Zod schemas or direct JSON schemas to describe the shape of tool input, and then you can run the tools using the `client.beta.messages.toolRunner` method. This method will automatically handle passing the inputs generated by the model into your tools and providing the results back to the model. + +```ts +import OpenAI from 'openai'; + +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; +import { z } from 'zod/v4'; + +const client = new OpenAI(); + +async function main() { + const addTool = betaZodFunctionTool({ + name: 'add', + parameters: z.object({ + a: z.number(), + b: z.number(), + }), + description: 'Add two numbers together', + run: (input) => { + return String(input.a + input.b); + }, + }); + + const multiplyTool = betaZodFunctionTool({ + name: 'multiply', + parameters: z.object({ + a: z.number(), + b: z.number(), + }), + description: 'Multiply two numbers together', + run: (input) => { + return String(input.a * input.b); + }, + }); + + const finalMessage = await client.beta.chat.completions.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + messages: [{ role: 'user', content: 'What is 5 plus 3, and then multiply that result by 4?' }], + tools: [addTool, multiplyTool], + }); + console.log(finalMessage); +} + +main(); +``` + ## Webhook Verification Verifying webhook signatures is _optional but encouraged_. diff --git a/examples/tool-calls-beta-zod.ts b/examples/tool-calls-beta-zod.ts index 80c5192cc..8a5619f17 100755 --- a/examples/tool-calls-beta-zod.ts +++ b/examples/tool-calls-beta-zod.ts @@ -1,7 +1,7 @@ #!/usr/bin/env -S npm run tsn -T import OpenAI from 'openai'; -import { betaZodTool } from 'openai/helpers/beta/zod'; +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; import { z } from 'zod'; const client = new OpenAI(); @@ -15,7 +15,7 @@ async function main() { }, ], tools: [ - betaZodTool({ + betaZodFunctionTool({ name: 'getWeather', description: 'Get the weather at a specific location', parameters: z.object({ @@ -25,7 +25,7 @@ async function main() { return `The weather is sunny with a temperature of 20°C in ${location}.`; }, }), - betaZodTool({ + betaZodFunctionTool({ name: 'getTime', description: 'Get the current time in a specific timezone', parameters: z.object({ @@ -35,7 +35,7 @@ async function main() { return `The current time in ${timezone} is 3:00 PM.`; }, }), - betaZodTool({ + betaZodFunctionTool({ name: 'getCurrencyExchangeRate', description: 'Get the exchange rate between two currencies', parameters: z.object({ diff --git a/examples/tool-helpers-advanced-streaming.ts b/examples/tool-helpers-advanced-streaming.ts index 12770331e..458ef38dc 100755 --- a/examples/tool-helpers-advanced-streaming.ts +++ b/examples/tool-helpers-advanced-streaming.ts @@ -1,7 +1,7 @@ #!/usr/bin/env -S npm run tsn -T import OpenAI from 'openai'; -import { betaZodTool } from 'openai/helpers/beta/zod'; +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; import { z } from 'zod'; const client = new OpenAI(); @@ -15,7 +15,7 @@ async function main() { }, ], tools: [ - betaZodTool({ + betaZodFunctionTool({ name: 'getWeather', description: 'Get the weather at a specific location', parameters: z.object({ @@ -25,7 +25,7 @@ async function main() { return `The weather is sunny with a temperature of 20°C in ${location}.`; }, }), - betaZodTool({ + betaZodFunctionTool({ name: 'getTime', description: 'Get the current time in a specific timezone', parameters: z.object({ @@ -35,7 +35,7 @@ async function main() { return `The current time in ${timezone} is 3:00 PM.`; }, }), - betaZodTool({ + betaZodFunctionTool({ name: 'getCurrencyExchangeRate', description: 'Get the exchange rate between two currencies', parameters: z.object({ diff --git a/examples/tool-helpers-advanced.ts b/examples/tool-helpers-advanced.ts index 8875dcb6f..43d67c9b8 100755 --- a/examples/tool-helpers-advanced.ts +++ b/examples/tool-helpers-advanced.ts @@ -1,7 +1,7 @@ #!/usr/bin/env -S npm run tsn -T import OpenAI from 'openai'; -import { betaZodTool } from 'openai/helpers/beta/zod'; +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; import { z } from 'zod'; const client = new OpenAI(); @@ -15,7 +15,7 @@ async function main() { }, ], tools: [ - betaZodTool({ + betaZodFunctionTool({ name: 'getWeather', description: 'Get the weather at a specific location', parameters: z.object({ diff --git a/helpers.md b/helpers.md index 268a0abe9..6b26b3400 100644 --- a/helpers.md +++ b/helpers.md @@ -302,6 +302,128 @@ If you need to cancel a stream, you can `break` from a `for await` loop or call See an example of streaming helpers in action in [`examples/stream.ts`](examples/stream.ts). +### Automated function calls via Beta Tool Runner + +We now offer an easier to use tool calling approach via the `openai.beta.chat.completions.toolRunner({…})` helper. The SDK provides helper functions to create runnable tools that can be automatically invoked by the .toolRunner() method. These helpers simplify tool creation with JSON Schema or Zod validation. + +#### Usage + +```ts +import OpenAI from 'openai'; + +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; +import { z } from 'zod/v4'; + +const client = new OpenAI(); + +async function main() { + const addTool = betaZodFunctionTool({ + name: 'add', + parameters: z.object({ + a: z.number(), + b: z.number(), + }), + description: 'Add two numbers together', + run: (input) => { + return String(input.a + input.b); + }, + }); + + const multiplyTool = betaZodFunctionTool({ + name: 'multiply', + parameters: z.object({ + a: z.number(), + b: z.number(), + }), + description: 'Multiply two numbers together', + run: (input) => { + return String(input.a * input.b); + }, + }); + + const finalMessage = await client.beta.chat.completions.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + messages: [{ role: 'user', content: 'What is 5 plus 3, and then multiply that result by 4?' }], + tools: [addTool, multiplyTool], + }); + console.log(finalMessage); +} + +main(); +``` + +#### Advanced Usage + +You can also use the `toolRunner` as an async generator to act as the logic runs in. + +```ts +// or, instead of using "await client.beta.messages.toolRunner", you can use: +const toolRunner = client.beta.chat.completions.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + messages: [{ role: 'user', content: 'What is 5 plus 3, and then multiply that result by 4?' }], + tools: [addTool, multiplyTool], +}); + +for await (const event of toolRunner) { + console.log(event.choices[0]!.message.content); + + // If the most recent message triggered a tool call, you can get the result of + // that tool call + const toolResponse = await toolRunner.generateToolResponse(); + console.log(toolResponse); +} +``` + +When you just "await" the `toolRunner`, it simply automatically iterates until the end of the async generator. + +#### Streaming + +```ts +const runner = anthropic.beta.messages.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + messages: [{ role: 'user', content: 'What is the weather in San Francisco?' }], + tools: [calculatorTool], + stream: true, +}); + +// When streaming, the runner returns ChatCompletionStream +for await (const messageStream of runner) { + for await (const event of messageStream) { + console.log('event:', event); + } + console.log('message:', await messageStream.finalMessage()); +} + +console.log(await runner); +``` + +See [./examples/tool-helpers-advanced-streaming.ts] for a more in-depth example. + +#### Beta Zod Tool + +Zod schemas can be used to define the input schema for your tools: + +```ts +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; + +const weatherTool = betaZodFunctionTool({ + name: 'get_weather', + inputSchema: z.object({ + location: z.string().describe('The city and state, e.g. San Francisco, CA'), + unit: z.enum(['celsius', 'fahrenheit']).default('fahrenheit'), + }), + description: 'Get the current weather in a given location', + run: async (input) => { + return `The weather in ${input.location} is ${input.unit === 'celsius' ? '22°C' : '72°F'}`; + }, +}); +``` + +The AI's generated inputs will be directly validated and fed into your function automatically. + ### Automated function calls We provide the `openai.chat.completions.runTools({…})` @@ -317,6 +439,8 @@ Otherwise, the args will be passed to the function you provide as a string. If you pass `tool_choice: {function: {name: …}}` instead of `auto`, it returns immediately after calling that function (and only loops to auto-recover parsing errors). +#### Beta Tool + ```ts import OpenAI from 'openai'; diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 8a5431e1c..53176a5a2 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -9,7 +9,7 @@ import type { FunctionTool } from '../../resources/beta'; * converted into JSON Schema when passed to the API. The provided function's * input arguments will also be validated against the provided schema. */ -export function betaZodTool(options: { +export function betaZodFunctionTool(options: { name: string; parameters: InputSchema; description: string; diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 9cab239b2..e91ae4a41 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -124,7 +124,7 @@ export class BetaToolRunner this.#toolResponse = undefined; this.#iterationCount++; - const { max_iterations, ...params } = this.#state.params; + const { max_iterations: _, ...params } = this.#state.params; if (params.stream) { stream = this.client.chat.completions.stream({ ...params, stream: true }, this.#options); diff --git a/tests/lib/tools/BetaToolRunnerE2E.test.ts b/tests/lib/tools/BetaToolRunnerE2E.test.ts index ee32ddc23..017422ce8 100644 --- a/tests/lib/tools/BetaToolRunnerE2E.test.ts +++ b/tests/lib/tools/BetaToolRunnerE2E.test.ts @@ -1,5 +1,5 @@ import { OpenAI } from '../../../src'; -import { betaZodTool } from '../../../src/helpers/beta/zod'; +import { betaZodFunctionTool } from '../../../src/helpers/beta/zod'; import * as z from 'zod'; import nock from 'nock'; import { gunzipSync } from 'zlib'; @@ -102,7 +102,7 @@ describe('toolRunner integration tests', () => { run: (args: any) => any; }> = {}, ) { - return betaZodTool({ + return betaZodFunctionTool({ name: 'test_tool', parameters: z.object({ value: z.string() }), description: 'A test tool', @@ -112,7 +112,7 @@ describe('toolRunner integration tests', () => { } function createCounterTool() { - return betaZodTool({ + return betaZodFunctionTool({ name: 'test_tool', parameters: z.object({ count: z.number() }), description: 'A test tool', From c1dd29b3464e4722b6e36a4ee91c8538723cb9fb Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 16:43:42 -0500 Subject: [PATCH 28/43] more readme work --- README.md | 6 ++++++ helpers.md | 10 +++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b2b7c4020..c24fdefbf 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,8 @@ await client.files.create({ ## Streaming Helpers +The SDK makes it easy to stream responses, by providing an emitter helper via `.stream()`: + ```ts import OpenAI from 'openai'; @@ -154,6 +156,10 @@ async function main() { main(); ``` +With `.stream()` you get event handlers, accumulation, and an async iterable. + +Alternatively, you can use `client.chat.completions({ ..., stream: true })` which only returns an async iterable of the events in the stream and thus uses less memory (it does not build up a final message object for you). + ## Tool Helpers The SDK makes it easy to create and run [function tools with the chats API](https://platform.openai.com/docs/guides/function-calling). You can use Zod schemas or direct JSON schemas to describe the shape of tool input, and then you can run the tools using the `client.beta.messages.toolRunner` method. This method will automatically handle passing the inputs generated by the model into your tools and providing the results back to the model. diff --git a/helpers.md b/helpers.md index 6b26b3400..fd9d7af34 100644 --- a/helpers.md +++ b/helpers.md @@ -304,7 +304,7 @@ See an example of streaming helpers in action in [`examples/stream.ts`](examples ### Automated function calls via Beta Tool Runner -We now offer an easier to use tool calling approach via the `openai.beta.chat.completions.toolRunner({…})` helper. The SDK provides helper functions to create runnable tools that can be automatically invoked by the .toolRunner() method. These helpers simplify tool creation with JSON Schema or Zod validation. +The SDK provides a convenient tool runner helper at `openai.beta.chat.completions.toolRunner({…})` that simplifies [function tool calling](https://platform.openai.com/docs/guides/function-calling). This helper allows you to define functions with their associated schemas, and the SDK will automatically invoke them as the AI requests and validate the parameters for you. #### Usage @@ -376,6 +376,8 @@ for await (const event of toolRunner) { } ``` +The tool runner will invoke the AI with your tool offering and initial message history, and then the AI may respond by invoking your tools. Eventually the AI will respond without a tool call message, which is the "final" message in the chain. As the AI repeatedly invokes tools, you can view the responses via the async iterator. + When you just "await" the `toolRunner`, it simply automatically iterates until the end of the async generator. #### Streaming @@ -424,9 +426,9 @@ const weatherTool = betaZodFunctionTool({ The AI's generated inputs will be directly validated and fed into your function automatically. -### Automated function calls +### Legacy Automated function calls -We provide the `openai.chat.completions.runTools({…})` +We also provide the `openai.chat.completions.runTools({…})` convenience helper for using function tool calls with the `/chat/completions` endpoint which automatically call the JavaScript functions you provide and sends their results back to the `/chat/completions` endpoint, @@ -439,8 +441,6 @@ Otherwise, the args will be passed to the function you provide as a string. If you pass `tool_choice: {function: {name: …}}` instead of `auto`, it returns immediately after calling that function (and only loops to auto-recover parsing errors). -#### Beta Tool - ```ts import OpenAI from 'openai'; From 5a9cb4bdb5b5389c9ab028668f29ff584d83a13d Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 17:17:17 -0500 Subject: [PATCH 29/43] remove object check --- src/helpers/beta/zod.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 53176a5a2..b5e269e51 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -17,10 +17,6 @@ export function betaZodFunctionTool(options: { }): BetaRunnableTool> { const jsonSchema = z.toJSONSchema(options.parameters, { reused: 'ref' }); - if (jsonSchema.type !== 'object') { - throw new Error(`Zod schema for tool "${options.name}" must be an object, but got ${jsonSchema.type}`); - } - // TypeScript doesn't narrow the type after the runtime check, so we need to assert it const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; From d18bbfbcb4984048cac6911a551035baa8375212 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Wed, 3 Dec 2025 17:54:28 -0500 Subject: [PATCH 30/43] add image tool --- src/helpers/beta/zod.ts | 4 +- src/lib/beta/BetaRunnableTool.ts | 5 +- tests/lib/tools/BetaToolRunner.test.ts | 58 ++++ tests/lib/tools/BetaToolRunnerE2E.test.ts | 46 +++- tests/lib/tools/logo.png | Bin 0 -> 37833 bytes tests/lib/tools/nockFixtures/ToolRunner.json | 271 +++++++++++++++---- 6 files changed, 319 insertions(+), 65 deletions(-) create mode 100644 tests/lib/tools/logo.png diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index b5e269e51..ae61f2808 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -1,7 +1,7 @@ import type { infer as zodInfer, ZodType } from 'zod/v4'; import * as z from 'zod/v4'; import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; -import type { FunctionTool } from '../../resources/beta'; +import type { ChatCompletionContentPart } from '../../resources'; /** * Creates a tool using the provided Zod schema that can be passed @@ -13,7 +13,7 @@ export function betaZodFunctionTool(options: { name: string; parameters: InputSchema; description: string; - run: (args: zodInfer) => Promisable>; // TODO: I changed this but double check + run: (args: zodInfer) => Promisable; }): BetaRunnableTool> { const jsonSchema = z.toJSONSchema(options.parameters, { reused: 'ref' }); diff --git a/src/lib/beta/BetaRunnableTool.ts b/src/lib/beta/BetaRunnableTool.ts index b17cac29c..8479bcbf4 100644 --- a/src/lib/beta/BetaRunnableTool.ts +++ b/src/lib/beta/BetaRunnableTool.ts @@ -1,11 +1,10 @@ -import { FunctionTool } from '../../resources/beta'; -import type { ChatCompletionTool } from '../../resources'; +import type { ChatCompletionContentPart, ChatCompletionTool } from '../../resources'; export type Promisable = T | Promise; // this type is just an extension of BetaTool with a run and parse method // that will be called by `toolRunner()` helpers export type BetaRunnableTool = ChatCompletionTool & { - run: (args: Input) => Promisable>; + run: (args: Input) => Promisable; parse: (content: unknown) => Input; }; diff --git a/tests/lib/tools/BetaToolRunner.test.ts b/tests/lib/tools/BetaToolRunner.test.ts index bd78b8c4e..04c53dcdb 100644 --- a/tests/lib/tools/BetaToolRunner.test.ts +++ b/tests/lib/tools/BetaToolRunner.test.ts @@ -11,6 +11,7 @@ import type { } from 'openai/resources'; import type { Fetch } from 'openai/internal/builtin-types'; import type { BetaToolRunnerParams } from 'openai/lib/beta/BetaToolRunner'; +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; const weatherTool: BetaRunnableTool<{ location: string }> = { type: 'function', @@ -1007,6 +1008,63 @@ describe('ToolRunner', () => { expect(runner.params.messages[2]).toMatchObject(getWeatherToolResult('Paris', 'tool_1')); await expectDone(iterator); }); + + it('allows you to use non-string returning custom tools', async () => { + const customTool: BetaRunnableTool<{ location: string }> = { + type: 'function', + function: { + name: 'getWeather', + description: 'Get the weather in a given location', + parameters: { + type: 'object', + properties: { + location: { type: 'string' }, + }, + }, + }, + run: async ({ location }) => { + return [ + { + type: 'image_url' as const, + image_url: { + url: `https://example.com/weather-${location}.jpg`, + }, + }, + ]; + }, + parse: (input: unknown) => input as { location: string }, + }; + + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'Test done method' }], + tools: [customTool], + }); + + const iterator = runner[Symbol.asyncIterator](); + + // Assistant requests the custom tool + handleAssistantMessage([getWeatherToolUse('Paris')]); + await expectEvent(iterator, (message) => { + expect(message?.choices[0]?.message?.tool_calls).toMatchObject([getWeatherToolUse('Paris')]); + }); + + // Verify generateToolResponse returns the custom tool result + const toolResponse = await runner.generateToolResponse(); + expect(toolResponse).toMatchObject([ + { + role: 'tool', + tool_call_id: 'tool_1', + content: JSON.stringify([ + { + type: 'image_url', + image_url: { + url: 'https://example.com/weather-Paris.jpg', + }, + }, + ]), + }, + ]); + }); }); describe('.runUntilDone()', () => { diff --git a/tests/lib/tools/BetaToolRunnerE2E.test.ts b/tests/lib/tools/BetaToolRunnerE2E.test.ts index 017422ce8..5f24a8155 100644 --- a/tests/lib/tools/BetaToolRunnerE2E.test.ts +++ b/tests/lib/tools/BetaToolRunnerE2E.test.ts @@ -1,9 +1,10 @@ import { OpenAI } from '../../../src'; import { betaZodFunctionTool } from '../../../src/helpers/beta/zod'; -import * as z from 'zod'; +import { z } from 'zod/v4'; import nock from 'nock'; import { gunzipSync } from 'zlib'; import { RequestInfo } from 'openai/internal/builtin-types'; +import * as fs from 'node:fs/promises'; describe('toolRunner integration tests', () => { let client: OpenAI; @@ -272,4 +273,47 @@ describe('toolRunner integration tests', () => { expect(params.messages).toEqual([{ role: 'user', content: 'Updated message' }]); }); }); + + describe('Non string returning tools', () => { + it('should handle non-string returning tools', async () => { + const exampleImageBuffer = await fs.readFile(__dirname + '/logo.png'); + const exampleImageBase64 = exampleImageBuffer.toString('base64'); + const exampleImageUrl = `data:image/png;base64,${exampleImageBase64}`; + + const tool = betaZodFunctionTool({ + name: 'cool_logo_getter_tool', + description: 'query for a company logo', + parameters: z.object({ + name: z.string().min(1).max(100).describe('the name of the company whose logo you want'), + }), + run: async () => { + return [ + { + type: 'image_url' as const, + image_url: { + url: exampleImageUrl, + }, + }, + ]; + }, + }); + + const runner = client.beta.chat.completions.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + messages: [ + { + role: 'user', + content: + 'what is the dominant colour of the logo of the company "Stainless"? One word response nothing else', + }, + ], + tools: [tool], + }); + + const finalMessage = await runner.runUntilDone(); + const color = finalMessage.content?.toLowerCase(); + expect(['blue', 'black', 'gray', 'grey']).toContain(color); // ai is bad at colours apparently + }); + }); }); diff --git a/tests/lib/tools/logo.png b/tests/lib/tools/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..5072d80ad1b1c66f9bf30138bc449b740b9eb306 GIT binary patch literal 37833 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 N002ovPDHLkV1n8ynGgT~ literal 0 HcmV?d00001 diff --git a/tests/lib/tools/nockFixtures/ToolRunner.json b/tests/lib/tools/nockFixtures/ToolRunner.json index e50620c0a..6e8f77d0a 100644 --- a/tests/lib/tools/nockFixtures/ToolRunner.json +++ b/tests/lib/tools/nockFixtures/ToolRunner.json @@ -29,32 +29,31 @@ } } ], - "n": 1, "stream": false }, "status": 200, "response": [ - "1b3404201c07ce392f9674370bc94efe64a16ed37e734d47c4f46b02248853a8e715babcf24ab4b4751458fa1e5cee9f9f1fed996e36d6f036f7636283a76818269c52b6d588a0ad3e11418db6ae8ef6eceed37f288f0022f9b3f0cc4f622d2f98957da6dbeaf2e23693e2f7736deb75377ae562146043431445cf0f482009ee670654e57dc3b61dd35416b411e6dd943f44838969da1315e75cb276ce7f737f37f08f218d7b0514e1268fa20b723b7463a7a98ab89f60b8645803967b31604891a8a57dd392fd97ea2a90fd07aa18c5477b76da3abfde9f8bda64d12959b35ef4312d2016ac12be20118574245e18820bea40de153d183b35cfaa6106d1e17f8f102ff7f0f45ef738b6abd76576bdc17f68f08a7f7293879ad8cadbaa1792b74e2ce53716dcb54b55a012a58be17778295bd88af39e31adc5b7e5993f28d90feec0d2e64c8cf3e0b66a608a7820dbb6fc0f2c13ffbd9e2f96e1e548c6cf36cc6e2f469607db13f5f1e4809bf34b7a282605a14cef074f377e49fe50932375b3759cf5c7f4c8e31b401d459cea4299bee083e506e9fb9593e5b8811f39b1eba30b" + "1b3404201c07ce392f9674370bc94efe64f1767ed54f1dbc83ca00f8dc233630857a5ea1cb2baf444b5b4781a5efc1e5fef96da1c574b33df0bdcdfd98d8e0291a96259c52b6d9081af58908eab4393ded59bdfb0c253e40247fe6159cd73bc949dc0fafa13e6be74bbe8b6ed43f9d85bbf9e68e3cc58686288aa10f482009eee733900c5d3585ac0a6b431b61de8ef85a57ab7a9a4eebc23c36f58df3dfdcfd19f8fb82c6bd04a27691473101b92d3a57f9d441dc8f305c32ac0fcbc31830a441d4d2be6dcaff545d05b2ff4041a66e17e7cd93b3acd4dce4d197a6616bb2f8c2b48058b048f8e24414d2918461082ea803799774adaabc85160d33882e3ebf08b1ff0b4feff917c77af13a2daf37f887062f38b99b42d4c4d6dad6b990bc9457119f2bf7a2ddac0235295d8ca8c39bd9c2569c768b69375efd82af94ec7b17a0cb7329c685704f523145429067e8d11bb688ff61cf37caf0962f13651b66771823cbe3ed497b7b72c0d54919ed8a494168d1f321d44d54925fd45491bad93acefa43ba26c119a08e224e75a1456ff0c17283f4fdcaa49b96ebf8666039e802" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a845d712abc8c27-EWR", + "cf-ray": "9a86a3f37a6c435d-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 16:15:50 GMT", + "date": "Wed, 03 Dec 2025 22:53:30 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "375", + "openai-processing-ms": "463", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=23PiD.Xem7RLutUsn3Z8kgcrKzxIJ6umxTQi.bA72wI-1764778550408-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=GlEUF5eZNs03lLp5zRSOEDHk56nmLNOJOldO2p5ssKc-1764802410058-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "388", + "x-envoy-upstream-service-time": "475", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -62,7 +61,7 @@ "x-ratelimit-remaining-tokens": "29999974", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_f7524cf93f5a4270a594f5dd1572b544" + "x-request-id": "req_09a247f38acb4c9f8f52a172079fc911" }, "responseIsBinary": false }, @@ -83,7 +82,7 @@ "content": null, "tool_calls": [ { - "id": "call_A4jx2uIH3pqsuUCQUIkoFDjL", + "id": "call_ek4TOrSxpkkn5biwF1LfAKOY", "type": "function", "function": { "name": "test_tool", @@ -97,7 +96,7 @@ { "role": "tool", "content": "Tool result", - "tool_call_id": "call_A4jx2uIH3pqsuUCQUIkoFDjL" + "tool_call_id": "call_ek4TOrSxpkkn5biwF1LfAKOY" } ], "tools": [ @@ -117,32 +116,31 @@ } } ], - "n": 1, "stream": false }, "status": 200, "response": [ - "1b8003209c0576b33291acec5a442b1f61a0ca79859aaa9fe8d9e29cca471707247fc59c31b7028bce9c38f1fbbf6fe7f3a795120a3c96eebc99d61d344cd7fb6bb7bc1d300dcb124e616cda093da63ef2d3a365212420f9b7a06a4bbaccf2c698c760b82dae61f47a9e2e52f3fb5325f7cf8b07a239d114d217487032d49cef90d23434d3b4745df462476493493b52ada1341d5261cdab46affcf7461fec328f95dc9d8ffb82ec5457f4217928810d4c28e07e028aaba3513fafe6e85620ee44c5a902df19077b0d21f90145f8cfa5aaf34cce2486cf0bc7b86998b9fa0b0103af04b5588cb01617d7ae6dcc8d6f954dd2f68d3fa8ae46e92a863faf0c21b4039459e8c9f1e43d53b57d53b523f2067a762da338083c124fa42da18d85ce099da4350c4b0c4625b6d4423969e484292ce6acbeda429b6aefdc7e655627238b19b96a78ac6547a764ea871ee554f0677fcaa0318e59d46361c72411771cabe1a7e1087521eb77dca261d9be175a91ed0103" + "1bc303008cd31db5c83e163150e5bc424dd54ff4ec706dfd4b12934a72df8b623770bffffb763e472b651acb9ffb665a770dc374bdaf760bb74d2ccd224e233cdb8e3e283ff85f8fd616742c9d37e93bbfe1abd6691fe62ffd769df07a9def7e9bdeccb2fc7c31d93cf072998ae6a371d22f487024aae83b1d6b05be1b9ab66b991b1829e3e11abf3517349c7635333c28fa1b6d0082de1ed7a9c7428e873d44e15c75a341c7843a93e4888a4ce2f7689540bd964569f1bd2e95ebcde9835ffafa8f478311fc547f5e51e1f57331ed86980f1ab9a13522540042ec41031289db9afd0afe6471745e64eaec57c03e9005d4efcbc9df6fb2424e561f7bb6ebbf0c8ca657a08e2ea47a41d44ab7aa2c4e1f5da1c64fc85eecc59a8522aae1204f5779832666e1b870f9d8fd847824fc841b7e23ec89d066e84fb72a0022483a012a962e7b67d98e3a2aa17ae48416425ca920f2b30fb4f185cef6f9162d2bdf397f657baf777ca101b484da6bf6da23d52f4e4a2b13e8c8148545f46f122519d6ae81c0e1b484be5107f017b2df15467e1865691196514a1303" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a845d761f1c8c27-EWR", + "cf-ray": "9a86a3f77eeb435d-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 16:15:51 GMT", + "date": "Wed, 03 Dec 2025 22:53:31 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "596", + "openai-processing-ms": "1217", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=DxyeRhO5K1.8vDJnFHChY4psCYa11f1v643RPYuvmss-1764778551422-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=gzNuCbSDlJdjP._lZoOynHR4fBAUyEpe75aycbauflk-1764802411452-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "617", + "x-envoy-upstream-service-time": "1232", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -150,7 +148,7 @@ "x-ratelimit-remaining-tokens": "29999969", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_b8080ce1b79341bd940565c356af3ea5" + "x-request-id": "req_2d3aa717e10540eea7c247f7f4908154" }, "responseIsBinary": false }, @@ -184,32 +182,31 @@ } } ], - "n": 1, "stream": false }, "status": 200, "response": [ - "1b1205201c0776d356336ef452185b7fa24acf5f68b2ea256a6e49af69cf5c1d343ec4940f20755814feff7bf7e338b43085ce9ded01be0675ee6b2cdad826fb91a6141066d3869a74f1b118b387475b80039f767eff681d0310c9af45fbd3ceceac374765aecdc1bdbe3c5dd68c05224d44463fc9ad3f828f4c948e66010924c1f37c0688925c292d0439514768bdcbd3cde6473b4d6bb6a77f53f2e4fc0ff44f0efed524bb5b8067dd642baa40ae41b1811934ee7b302e195680e516038624915a3a37ee76f02aae02d95fc0763eb5bb7cf8592ffabdd32adedd9adb0bb9ad77702f20161c12be59220aa9251686e04277206f02d5d4af1e1a66106d7ea751383175fde13ff1cdddb87c5be99b7e778ad9866eec4f85fdf298ff841e9323521d97b788a9b6cd176afeb786d136870326eff073ece5abe776c7e52a21765d7ba72aaf29ac059ecba654bab01687dd099b6e91f3cdd30d2b198cdc94dac2364a27838738c7fc37d03b42a835621ab3db3a3d59fd4ac7326e2e61edb218b6dd5368d1e1c90357af0fcb4b312977697cfa99695c497e0d5558eae7e0b8a64de36d9d5c00784a204e552f8def27c2628acc9d3861124bce62f11e23a005" + "1b1205201c0776d356336ef452185b7fa2989c27747bf5885a4b7a4d7be6ea508d0f31255e4c1d1685e3ef5d9fe3d0c2146ebc7bf7c7b2164e1fbca7b7c9ca124e29516cd14de616939eb05737147b0044f26b6e7ecac45a7c565efae75d66ddf66d90b8dde43dac6ebb957cc4471e3c64a2251c588004832172de0344d7b8a1504ec88d75a46d7b78ba89bc14cbb4242ac66ba8dda4fe9dceddc03d70c5763bbe82c93f8a15458057a1d8b40088fb010c17a32b40960fc228437cf4afca96cbe27d555711ee2f20296ab591abdbf553f7e1d7ceca3398eb3565ca602a4a2c3ad8f08d4251905a3208a6e0123925af8f6aea450f1a6642ad7ef7a5b0bf77fdf13ff4c3efebf65bf9b7e01ad5fa902c86cfdec9353fcdc7c6bc16cb99564c05535d2d6ea8e5df1ac2764c0e0cd41def4e6dbeba2f2bc3a5845875a50e6baf21f682cc703685e9225a1c774fd8b4d3b1969f6ed8c9baae80666c172aa701788e73aeff01d03342a8c031c2ea1e747a50ff8a3c9ce15ae2de350833aa8f566852f6c60367c745f850986d77118e7e226624a6cc862a2ff573f6a5a7f5e22df62f008c120c375d2fc2f9137133e5ccfd7842df20a6cf38331ce803" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a845d7c7ba58c27-EWR", + "cf-ray": "9a86a3ffbf82435d-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 16:15:52 GMT", + "date": "Wed, 03 Dec 2025 22:53:31 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "760", + "openai-processing-ms": "380", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=fW433MHslfoC7JTSFlm4_zUnCx_1akGUNhJDEcL4e_c-1764778552600-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=njc6MDtQdrcZ26iMGVwB3ubObCHrz3QvBEaZhe68Z8s-1764802411945-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "783", + "x-envoy-upstream-service-time": "403", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -217,7 +214,7 @@ "x-ratelimit-remaining-tokens": "29999973", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_8b967c6196c74f4885ff26753d969711" + "x-request-id": "req_1dd8e9055e694885ab44d09d745397a8" }, "responseIsBinary": false }, @@ -238,7 +235,7 @@ "content": null, "tool_calls": [ { - "id": "call_RFAlrz4q8fVUphdltPkr1til", + "id": "call_1nCCOc7aDpJveCq0wfT7C0R3", "type": "function", "function": { "name": "test_tool", @@ -246,7 +243,7 @@ } }, { - "id": "call_BySHDO8OmpGmBILLU36Y1LZJ", + "id": "call_c8BDN1UNwKpc9zFvY9snVS6n", "type": "function", "function": { "name": "test_tool", @@ -260,12 +257,12 @@ { "role": "tool", "content": "Called with 1", - "tool_call_id": "call_RFAlrz4q8fVUphdltPkr1til" + "tool_call_id": "call_1nCCOc7aDpJveCq0wfT7C0R3" }, { "role": "tool", "content": "Called with 2", - "tool_call_id": "call_BySHDO8OmpGmBILLU36Y1LZJ" + "tool_call_id": "call_c8BDN1UNwKpc9zFvY9snVS6n" } ], "tools": [ @@ -285,32 +282,31 @@ } } ], - "n": 1, "stream": false }, "status": 200, "response": [ - "1b2503001c07762c33326c3cb8f9269f7e5da9fe7979c57850bb062de40651e8ea9b3a2c0a5337efb9cd890618cb37c6e0c09ea2b52c9d246191f6d0cd4e26f4abbe2d21885c0055fee664654a1fa2b8d0c6267f5da5ea7c571ec56eb8bd5e8d95e483dae010f0a8a46c7c4182042223fa06bcaa48aaaac9b2308b440a151a942d2d15b49f6634a7ed2c65960300c83f99d82526188779c25157653652004408415da4b90bc56f3080ccb5d0ef04915fe4fff863ac54b4eb46d5d0884897bdc2dd287994164159177693dc82e359869500037614a21656e68fe375c78487b22bb2b235ac9bdb005e9416907103c2161ad1265a0909a5fd48dbd0785364266cda76d7b67c457b6ede9468ef2668e8f325e66f4679b0366f2a2e601b11b1c9740b547e35112f55d0d826db79d56823af06881c2280e409b6f1ce1ad1c104b0b25f1a9eab48a20b8fe8327a" + "1b4403001c07762c637abc12dcb8c9083da735f773c4b91062b76e1085aebea9c3a23071ae9b158d273ac0b144240fa3ceab6c5a1fc28f8f2ffcb6d91809150523986ea99e7b05d5b76f08840e4028ff66a7454275c2927d4bd6d196cb7cddab7bde825ba89ea88ecfdbd30b87808d5ccfd617243022ec8d0a8053e41ab3bcc8f1442b4951d52f1a4acca93c0d2856bd28f2c24e004078c9897d23c370b2782cd9ca9ae18360852050e549d111f81d1660ada676e6510e6a2e7de7487613c81f7881ebcbfee51f6a2634ea5bcc56bc68add51dfa5fcf8f92dc2faadcaabb2b484b45c710200165365a49926ffed8b6261a28b6282d1a1dfbf81a7082b842043a122cd19069f3ae44851c53d501d1f6a80cc8eb4e6dbb9f867b9bc928dfafd1d8f119eb1f0c33bfb6995c86a8fa84d9b6ba23cabeb98810ef69e4cfa6415d6f42b70298586801265154fd953674fe5162bfbd4277554e730551502df400" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a845d8378c38c27-EWR", + "cf-ray": "9a86a402eb44435d-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 16:15:53 GMT", + "date": "Wed, 03 Dec 2025 22:53:32 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "346", + "openai-processing-ms": "439", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=1yYWcIHwMGbk77yjyEEnd1UAcxqAb8lTI6P7da_g0XE-1764778553298-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=co2Kcpyfm7ogh1QQ5SAZ9JXSOXl2SJBD3B_VQbO3n5c-1764802412509-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "361", + "x-envoy-upstream-service-time": "452", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -318,7 +314,7 @@ "x-ratelimit-remaining-tokens": "29999963", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_88771ad4f2e7420fb19f3172cfa904a8" + "x-request-id": "req_52b80bc7966442caa0f3c3f87c357d91" }, "responseIsBinary": false }, @@ -344,7 +340,7 @@ "parameters": { "type": "object", "properties": { - "input": { + "value": { "type": "string" } } @@ -352,32 +348,31 @@ } } ], - "n": 1, "stream": false }, "status": 200, "response": [ - "1b3404201c07ce392f9674370bc94efe64d1b6529f8c69864f6e8bf91dbc18857a5ea1cb2baf444b5b4781a5efcf5fee8eb38516436ffef6c0f33677636283a7685896704ad95623825dea1311d468ebea68cfeedefd87ca0420923f8b5bde885e5931f73b5317e5c77bbaa78f3352fdbb53e45bf33e3f6143535445cf0f48600919e733506dcbb06dc734f59d6cc4b69df3876830314da7a2e29c9bd62ef96fef9e07feb1a0792f8122dc94594c406e8b06d62c1dc4fd08c335c3fab0dc8b21431a442d33769eecbf34ae42d97f204fe9fcefe6ee1e7da31f1f3bf3154fe3e77ab3c6b49058b86af882440c6466e28531b8a88ee45dd283b1a67b561366145dfc2f08ba7381a7f77cc1b15dbc2eb3eb0df943839516e2260f35a9b7b6772e242f352ce7038beedacd2a5093d2c5f23bbc992d62c569cf9876e39bd3f20725fbde1d586acbc4380f5e520d4a110f54b24dff035bc47fafe71b65782b91f1b38db2db8bb1e5c1f6447d3c3be0eab2cb0f83694168d1fbc1338c5f523ed454967173ee24eb0fe951a603401d259ceb428bbee043e586e8fb9553eaa86eaa1bba13a10b" + "1b3404201c07762cf8856ed59074e213857a5ea1cb2baf444b2db2b3eaa77eb10e847d30da0bdc3a0a2c7d0f2e97670b2d96dbcde58f8dc9fd98d8e0291a96259c52b69948a1d27eca1874a789d1d33dbbbdfb43650290c99fc56771922be555fb3e9e666b7cffda3a5ffdc573502beeafbcfb301c6c68896ae8f90109ac21f37c06baeb589e6658ba71918fb86fe7e2215b2c97e954d6bc77195aea1f646b33e0e10c5af71268d287b28a09e86dd18d4f5b07793fc270adb03e2cf762c8900651cbe62e90fdb7162ad4fd072ab3a231ca5bfa40f052fb76e6a2e5cdd8abfd302b24161e9abe2015836c255e18938be648de253d984fe2392ccd200efe5ba4d8d9c2b37bdee2382f5eb7d98d86fca1c10be1294c1e6a92b4563a9792974e9c8b1b4777eb661da849e592f307bc952fecc569cf9c7613a773160f2af6bd3b70f43d13e33c7859b7a8443c50d9b5fd03b688ffdec837aaf056a2e3671b55b71763cf83fd893a3c07e0eaf292bf0cd386d0a2ef07cf347e4d7950534516e6fc49d51fd2a34c6f007d9470ee0b2d7a820fb51ba2ef57418ee74761e2a57e882e" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a845d877c0e8c27-EWR", + "cf-ray": "9a86a4064fc8435d-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 16:15:54 GMT", + "date": "Wed, 03 Dec 2025 22:53:33 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "485", + "openai-processing-ms": "470", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=ypLA4M9G6mnG7MBUSFm_Iglqo2scXgDPcHoPMb.wzeM-1764778554082-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=qctelHPmKFwZxEGKa9moqi.5BiaEpb9Ex33a4SA9UD8-1764802413080-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "507", + "x-envoy-upstream-service-time": "484", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -385,7 +380,7 @@ "x-ratelimit-remaining-tokens": "29999976", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_074137d9ba50430ba0f643913c8eaf97" + "x-request-id": "req_f366c98e66c0448e9288f900472afbae" }, "responseIsBinary": false }, @@ -406,11 +401,11 @@ "content": null, "tool_calls": [ { - "id": "call_C0nDyTs9YD4qKYn5vcMcuSTS", + "id": "call_ifhGQgI1OpoX0yKVpI8Uo8Ez", "type": "function", "function": { "name": "test_tool", - "arguments": "{\"input\":\"test\"}" + "arguments": "{\"value\":\"test\"}" } } ], @@ -420,7 +415,7 @@ { "role": "tool", "content": "Tool result", - "tool_call_id": "call_C0nDyTs9YD4qKYn5vcMcuSTS" + "tool_call_id": "call_ifhGQgI1OpoX0yKVpI8Uo8Ez" } ], "tools": [ @@ -432,7 +427,7 @@ "parameters": { "type": "object", "properties": { - "input": { + "value": { "type": "string" } } @@ -440,32 +435,31 @@ } } ], - "n": 1, "stream": false }, "status": 200, "response": [ - "1b2303201c07762c33326c3cb8f92623e696eaeef34c23125d262640832874f54d1d1685a99bf7dce64c63f96f6f0eec295acbd24912166907799b1478f077f5f60d81d001f0e46f765a24d4228cf2599e6ecc7dbf56fafdf27c5e4fab3d57b1f7cdc1c121a0a282d8f801091284cce71b708a2c2a8a2a49e24594110db85f34949853699a51acfa68c91739ff41feccc17f63426fd8262cf9a1ac450a701841a0ca93d685df37f87b5969b4ee7881bbca7fe38f331331ac1b43c321a258f63af72fc8a324f78b2ab76a6c0b7967e941020c8451886638986f85d7ad0e1e8aa5488b460f6e443352a569010b37beb7f9418c88261aa5b4e9d9babb9bf63211d0b603d336ae18cccdef24c1bbc5194a5ed2fc6698f9b7e6774afcdb7a396caadc8294cf4b2448b532f19783bcaa37a15b01940df17b290d6cfd8435627621a8b257e8ae238b82038e69127a" + "1b2303201c076eac66e4a4919313a8725ea1a6ea277ab638a7f2d1e5b1deef802465009c3a2c0a5337efb9cd99c6f2ffedc98175be96a593242c4b3815dd1093a4f20e9e1e2d8f8020c9dfc2baaba89bf7e2781c93785cfcf3784a9bdb3defdaa7dddf9b7708a341942fac7d40827886f49c77a0b44cdd164a975a8fdf1165c5b49ba8de52334da9b0e7a6d94bf60fb20f76fca3116e18c782ec945024e0bc8236b455ec80dc57f0710934aa374a9383f41b7f9c5f61b5ae653581e0d7b22e71f622b7aa36ed863618af36b33b139504e8a0460154c2cc38c0cb19835b57e57537a172a37b86b651cc62b876dc5219d688fa6594d5bc9f85e2aef365a4d056744e935cacccf563e28bb7bf4edfdb8bc82fe64d3ad68fc9fa6fa13bac436e9c29854b2448619998a4e4659cf2780082dbc0c74533b030c01a6c5de8acefa443d376023fb263c78706" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a845d8ea9d58c27-EWR", + "cf-ray": "9a86a409db58435d-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 16:15:55 GMT", + "date": "Wed, 03 Dec 2025 22:53:33 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "379", + "openai-processing-ms": "342", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=nv4APHcc7JiLRnjDkeab5uhoAoOa3wZ0qYhw8ZbJtUg-1764778555117-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=mkbGgtSFKFMkke2kByPwDtuVbhx0DLDoBzWnqQlafXA-1764802413537-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "391", + "x-envoy-upstream-service-time": "368", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -473,7 +467,166 @@ "x-ratelimit-remaining-tokens": "29999971", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_bdb05ea440404ab4b82c83580f7cd7ed" + "x-request-id": "req_5ed619a68f8649edab3b467e443ff656" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "what is the dominant colour of the logo of the company \"Stainless\"? One word response nothing else" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "cool_logo_getter_tool", + "description": "query for a company logo", + "parameters": { + "type": "object", + "properties": { + "name": { + "description": "the name of the company whose logo you want", + "type": "string", + "minLength": 1, + "maxLength": 100 + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b4504001c07ce393d16a9ec8a3af713a8723ea1a6ca3fd1b2953995af1eb15bee183b867ee75460d1393a35e170d0c2723b9d5bacb5d2fd77e2e2295a4cadc255aa6d26525896572923d3a8c99deed9aeaa01d30006a0fc995f36053b4a5be163d7a146b49594d371360e86f96a10d479b112a1806bd499ee091258451c7d8611754d31044911e59382c4d772dc10abd46c9e4e59c1f8686aa7148074f512805e70d0c2d3b1c07c2bcb18c38ad8111c7461c09f400a9a62fda1b91722451ac82d73ceefe38e6daf50f91f70d51ea699a4af8ce9493f7b516dcf8ee393a447d034641676c52fa663325b8a9723bae414434442ac611c12851dc66cc6ac1be6d016f03d131557b0ce0db969c5bbd72bfc9d7975c6c7bf3df20f07afb8c5be39ae526b7deb0ca3b78a3a6ebadaeba7372d494dcc9f2444a0291809e3dc07c82d1f0c7ed110663f9a6e99843892824e21170dca192f6b092d62b28519e1b16898f3ad4029e41fe5bb1772ecf188b6b5cf5b70735ac59709b544b4f017c3f90955e5d64d856ca3b3491d9822a50384442b2b2970a568e13d7da80011a1bf36181aa219ca8a6c786000" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a86a40cbe4b435d-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 22:53:34 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "371", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=MGROCDuDSefvEB1ljfMdWuWBHEINxZPtWYC1UYklq34-1764802414033-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "405", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999973", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_b8a24adeb2c14592b3b24feb0bcc725d" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "what is the dominant colour of the logo of the company \"Stainless\"? One word response nothing else" + }, + { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_QqWLj27Q8LY7ZbfoAMXJY27f", + "type": "function", + "function": { + "name": "cool_logo_getter_tool", + "arguments": "{\"name\":\"Stainless\"}" + } + } + ], + "refusal": null, + "annotations": [] + }, + { + "role": "tool", + "content": "[{\"type\":\"image_url\",\"image_url\":{\"url\":\"data:image/png;base64,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\"}}]", + "tool_call_id": "call_QqWLj27Q8LY7ZbfoAMXJY27f" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "cool_logo_getter_tool", + "description": "query for a company logo", + "parameters": { + "type": "object", + "properties": { + "name": { + "description": "the name of the company whose logo you want", + "type": "string", + "minLength": 1, + "maxLength": 100 + } + } + } + } + } + ], + "stream": false + }, + "status": 200, + "response": [ + "1b2e03801c07762ce6f638928adc64849ed39afb39e25888b10a2688425f2be8b0749dba79cf6dce34963126a751e76b591871382667736d6d9535f5d32b04410ebfd6d61702a183c08dcf765a24542b2c39567d4efad126c9ffa6fcb09dcc5696d778f5b6bd100b01fb04aed2d7237064be937d84536451657991132bab20b367fde246893915a311c5aa8f26573ef8417ca2905f54184d6f014bbee14d7051233e318e61c48b4e9f6144de62e6667c5129fc4ffc1166c282ba7496dcc12aa53f9b7f355625b95f54b955b36a883a4d87085000221752027131777ab7c04271256971d3a1cd084c0551e0946384212ed1759ec642a2860dd1aa2275dde5e5315301eaa9c31cb2a2152ca84b448dd5bf5ea5b6f2b9015886992fa58df8324188035d9f16f93e6a9bf1eb135112071bfaf360cfebb7d0ad104c1f2c910b075d5fb8868d32a6c9b757e8aeca69ae200aaa0503" + ], + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a86a4106afe435d-EWR", + "connection": "keep-alive", + "content-encoding": "br", + "content-type": "application/json", + "date": "Wed, 03 Dec 2025 22:53:34 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "390", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=GikF6GLf6kCnkR63rxdTSYYW7veAC4neKH6O0aUOC_M-1764802414640-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "transfer-encoding": "chunked", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "407", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29987343", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "25ms", + "x-request-id": "req_2ec3cfb9dd6c44f890f42034ca05d4b0" }, "responseIsBinary": false } From 658afef35bb40be64409710c2bebd593b0917eab Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 12:14:31 -0500 Subject: [PATCH 31/43] pass directly --- src/helpers/beta/zod.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index ae61f2808..9d34addaa 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -17,18 +17,12 @@ export function betaZodFunctionTool(options: { }): BetaRunnableTool> { const jsonSchema = z.toJSONSchema(options.parameters, { reused: 'ref' }); - // TypeScript doesn't narrow the type after the runtime check, so we need to assert it - const objectSchema = jsonSchema as typeof jsonSchema & { type: 'object' }; - return { type: 'function', function: { name: options.name, description: options.description, - parameters: { - type: 'object', - properties: objectSchema.properties, - }, + parameters: jsonSchema, }, run: options.run, parse: (args: unknown) => options.parameters.parse(args), From 9b0b3dff0a6f1efbae0018b9aeea4959cc72a382 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 12:17:02 -0500 Subject: [PATCH 32/43] add test for top level array --- tests/lib/tools/BetaToolRunnerE2E.test.ts | 32 +++ tests/lib/tools/nockFixtures/ToolRunner.json | 260 +++++++++++++------ 2 files changed, 217 insertions(+), 75 deletions(-) diff --git a/tests/lib/tools/BetaToolRunnerE2E.test.ts b/tests/lib/tools/BetaToolRunnerE2E.test.ts index 5f24a8155..4d57ee071 100644 --- a/tests/lib/tools/BetaToolRunnerE2E.test.ts +++ b/tests/lib/tools/BetaToolRunnerE2E.test.ts @@ -316,4 +316,36 @@ describe('toolRunner integration tests', () => { expect(['blue', 'black', 'gray', 'grey']).toContain(color); // ai is bad at colours apparently }); }); + + it('top level non-object schemas throw', async () => { + // At least for now, openai does not support non-object schemas at top level + const runner = client.beta.chat.completions.toolRunner({ + model: 'gpt-4o', + max_tokens: 1000, + max_iterations: 5, + messages: [ + { + role: 'user', + content: + 'Use the array_tool with the array ["hello", "world"], then provide a final response that includes the word \'foo\'.', + }, + ], + tools: [ + betaZodFunctionTool({ + name: 'array_tool', + description: 'Tool for array operations', + parameters: z.array(z.string()).describe('Array of strings'), + run: async (input: string[]) => { + return input.map((item) => item.toUpperCase()).join(', '); + }, + }), + ], + }); + await expect(async () => { + const messages = []; + for await (const message of runner) { + messages.push(message); + } + }).rejects.toThrow(); + }); }); diff --git a/tests/lib/tools/nockFixtures/ToolRunner.json b/tests/lib/tools/nockFixtures/ToolRunner.json index 6e8f77d0a..2d70510bc 100644 --- a/tests/lib/tools/nockFixtures/ToolRunner.json +++ b/tests/lib/tools/nockFixtures/ToolRunner.json @@ -19,12 +19,17 @@ "name": "test_tool", "description": "A test tool", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "value": { "type": "string" } - } + }, + "required": [ + "value" + ], + "additionalProperties": false } } } @@ -33,27 +38,27 @@ }, "status": 200, "response": [ - "1b3404201c07ce392f9674370bc94efe64f1767ed54f1dbc83ca00f8dc233630857a5ea1cb2baf444b5b4781a5efc1e5fef96da1c574b33df0bdcdfd98d8e0291a96259c52b6d9081af58908eab4393ded59bdfb0c253e40247fe6159cd73bc949dc0fafa13e6be74bbe8b6ed43f9d85bbf9e68e3cc58686288aa10f482009eee733900c5d3585ac0a6b431b61de8ef85a57ab7a9a4eebc23c36f58df3dfdcfd19f8fb82c6bd04a27691473101b92d3a57f9d441dc8f305c32ac0fcbc31830a441d4d2be6dcaff545d05b2ff4041a66e17e7cd93b3acd4dce4d197a6616bb2f8c2b48058b048f8e24414d2918461082ea803799774adaabc85160d33882e3ebf08b1ff0b4feff917c77af13a2daf37f887062f38b99b42d4c4d6dad6b990bc9457119f2bf7a2ddac0235295d8ca8c39bd9c2569c768b69375efd82af94ec7b17a0cb7329c685704f523145429067e8d11bb688ff61cf37caf0962f13651b66771823cbe3ed497b7b72c0d54919ed8a494168d1f321d44d54925fd45491bad93acefa43ba26c119a08e224e75a1456ff0c17283f4fdcaa49b96ebf8666039e802" + "1b3404201c07ce392f9674370bc94efe64819ed37e73c4b1103f64410af5bc4297575e8996b68e024bdf83cbfdf3db428be9667be07b9bfb31b1c153342c4b38a56cb31134ea1311d469737adab37af71f8a3d8048fecccdab8c6d257abb37c886ba7b6b2d16ca64fd749fbfd6f3b3bc698f01363444510c7d400249703f9f81a86b8aa119aa246d6823ccdb61f56095924dd3292b18c7a6b671fe9bbba781bf2f68dc4b20301779141390dba25b994d1dc4fd08c325c3fab03c8c01431a442deddba6fc4fd55520fb0fd4bc459be951694e8daaa3268654ef1b9bcd6adfc1b48058b048f8e24414d2918461082ea8037997f428cbac85160d33882efe6784d83fc3d37b3ee3582f5ea7e5f506ffd0e0053b7353889ad85adb3a179297b232ac6ea573d76e56819a942e46d4e1cd6c612b4e7bc6b45bb5fa79f5a064dfbb034d9a4b312e847ba2822912823c5d8bdeb045fc0f7bbe5186b73c9928db30bbc318591e6f4fdadb9303ae8e8b70574c0a428b9e0fa16ea292fca2a68ad4cdd671d61fd223f66f00751471aa0b2d7a830f961ba4efd78a7c43347d59910d075d" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a3f37a6c435d-EWR", + "cf-ray": "9a8cf2080f9d6e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:30 GMT", + "date": "Thu, 04 Dec 2025 17:15:22 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "463", + "openai-processing-ms": "416", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=GlEUF5eZNs03lLp5zRSOEDHk56nmLNOJOldO2p5ssKc-1764802410058-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=rXPneXdVZ1o5jQllF6SDrXFVxTPUc3cZnvKmc4fOGFA-1764868522844-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "475", + "x-envoy-upstream-service-time": "541", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -61,7 +66,7 @@ "x-ratelimit-remaining-tokens": "29999974", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_09a247f38acb4c9f8f52a172079fc911" + "x-request-id": "req_5568cd3e444146f0987483ecb85a557d" }, "responseIsBinary": false }, @@ -82,7 +87,7 @@ "content": null, "tool_calls": [ { - "id": "call_ek4TOrSxpkkn5biwF1LfAKOY", + "id": "call_BrhUNZ4BN8pE5j82qXAUUSXE", "type": "function", "function": { "name": "test_tool", @@ -96,7 +101,7 @@ { "role": "tool", "content": "Tool result", - "tool_call_id": "call_ek4TOrSxpkkn5biwF1LfAKOY" + "tool_call_id": "call_BrhUNZ4BN8pE5j82qXAUUSXE" } ], "tools": [ @@ -106,12 +111,17 @@ "name": "test_tool", "description": "A test tool", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "value": { "type": "string" } - } + }, + "required": [ + "value" + ], + "additionalProperties": false } } } @@ -120,27 +130,27 @@ }, "status": 200, "response": [ - "1bc303008cd31db5c83e163150e5bc424dd54ff4ec706dfd4b12934a72df8b623770bffffb763e472b651acb9ffb665a770dc374bdaf760bb74d2ccd224e233cdb8e3e283ff85f8fd616742c9d37e93bbfe1abd6691fe62ffd769df07a9def7e9bdeccb2fc7c31d93cf072998ae6a371d22f487024aae83b1d6b05be1b9ab66b991b1829e3e11abf3517349c7635333c28fa1b6d0082de1ed7a9c7428e873d44e15c75a341c7843a93e4888a4ce2f7689540bd964569f1bd2e95ebcde9835ffafa8f478311fc547f5e51e1f57331ed86980f1ab9a13522540042ec41031289db9afd0afe6471745e64eaec57c03e9005d4efcbc9df6fb2424e561f7bb6ebbf0c8ca657a08e2ea47a41d44ab7aa2c4e1f5da1c64fc85eecc59a8522aae1204f5779832666e1b870f9d8fd847824fc841b7e23ec89d066e84fb72a0022483a012a962e7b67d98e3a2aa17ae48416425ca920f2b30fb4f185cef6f9162d2bdf397f657baf777ca101b484da6bf6da23d52f4e4a2b13e8c8148545f46f122519d6ae81c0e1b484be5107f017b2df15467e1865691196514a1303" + "1b6303081c07ceb92e88a4d17588fa095439af5053f5133d5bb46bda33b73d617b68157380538145e77f2ef78e8f269dd0811fcbdf37769b03ebf95a96f71248c3b284d3cc0db5ed8bea4158cd3e3d5aecc14273fecdcdab8c6e126d7b3c3f4fc96ebd52edd3129e275b7b9d4ec2186f2708ad9c1a7aeb15098c4962df61054d9575555744c9a68ca2b41a561d954b4ad539e5756fa5da320a388b0f5af16359e1819ff284214519c1b0a8d840988c35fe1d0449c9511faed1d150db97d049d5d03253f99426cd18da0e2f4c83b264f1cb4f003d3b23626c015b6d4a25abcf6c5796b7b232ac9ad269a3a81aba15f633a7809e38026a825edcf6d5d05569cbbcea901e18f1585795ab1a690b8a04857ad536fb112f10b1c63eb35de965a4a83d70b7858810db00e77f7fae8e4d832be0c9b808dd6d4007518d53ea76c97770b9dc289555b63b21ca3a76b1dfc0c2d4431053a9c65b6f688822fa3ba8d0d705c397644977c000" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a3f77eeb435d-EWR", + "cf-ray": "9a8cf20c18206e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:31 GMT", + "date": "Thu, 04 Dec 2025 17:15:23 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "1217", + "openai-processing-ms": "474", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=gzNuCbSDlJdjP._lZoOynHR4fBAUyEpe75aycbauflk-1764802411452-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=LYGly6rnpgNHCOxOFA7QeHPRYzTurihkxtXwtc9CepA-1764868523447-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "1232", + "x-envoy-upstream-service-time": "491", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -148,7 +158,7 @@ "x-ratelimit-remaining-tokens": "29999969", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_2d3aa717e10540eea7c247f7f4908154" + "x-request-id": "req_3ac4e8a7e8aa46f39fc0e1d9c04bcddd" }, "responseIsBinary": false }, @@ -172,12 +182,17 @@ "name": "test_tool", "description": "A test tool", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "count": { "type": "number" } - } + }, + "required": [ + "count" + ], + "additionalProperties": false } } } @@ -186,27 +201,27 @@ }, "status": 200, "response": [ - "1b1205201c0776d356336ef452185b7fa2989c27747bf5885a4b7a4d7be6ea508d0f31255e4c1d1685e3ef5d9fe3d0c2146ebc7bf7c7b2164e1fbca7b7c9ca124e29516cd14de616939eb05737147b0044f26b6e7ecac45a7c565efae75d66ddf66d90b8dde43dac6ebb957cc4471e3c64a2251c588004832172de0344d7b8a1504ec88d75a46d7b78ba89bc14cbb4242ac66ba8dda4fe9dceddc03d70c5763bbe82c93f8a15458057a1d8b40088fb010c17a32b40960fc228437cf4afca96cbe27d555711ee2f20296ab591abdbf553f7e1d7ceca3398eb3565ca602a4a2c3ad8f08d4251905a3208a6e0123925af8f6aea450f1a6642ad7ef7a5b0bf77fdf13ff4c3efebf65bf9b7e01ad5fa902c86cfdec9353fcdc7c6bc16cb99564c05535d2d6ea8e5df1ac2764c0e0cd41def4e6dbeba2f2bc3a5845875a50e6baf21f682cc703685e9225a1c774fd8b4d3b1969f6ed8c9baae80666c172aa701788e73aeff01d03342a8c031c2ea1e747a50ff8a3c9ce15ae2de350833aa8f566852f6c60367c745f850986d77118e7e226624a6cc862a2ff573f6a5a7f5e22df62f008c120c375d2fc2f9137133e5ccfd7842df20a6cf38331ce803" + "1b1205001c0776d356336ef452185b7fa2989c27747bf5885a0b7a5e7fee8ae720a600c6d46151f0ffff6a333c1c5a98c25bfefd6f566e3b9e2fbcafde4e561625102165cd9606141f45a4d89d983dc7a7e9ab1bf22d0042f93333ce22b217c8fdf1d62cd4d33ebcf8dc7510476b27e6e6ad7ac91578c846df736006090e8281de03ac2c098aa4881c7fa892b2b6bb59450a2959a7359251be72e90001849db7813bb9a9e161ca40f557985105c00605a70540e00f6000ac6e00693e28941449d1c136383e8b776dbe12f0b7b85be98e1beff28ec075c4e37ebcec0d3f1fb39d80bb4966c9eee3370a63323365502ed195fe92bd29ea791286599c05dbfcdecbe1f4eefbe37ff8c3ef7afbcdfc5b6856697edaf2eb05634edfe67a55331ce39493ee5231676d71638dbf6b48eb982418283cdd4e6dceba2f4add6942ac2abbe7f16b8e64100ca7539e3250e3b83a638b6639dfcc2aa4b2ee1290144238504f0380922028010cc89eb12c47dcb2c0f21ef47a1681151668b89894bc06854ef7d11a4d7a7fe782b3fdc43d4de8f9aec0c71fc61909c57ba8ca3247470f52ebc5cab70b001e130a70b457e00b8a944d35753f66682bac6af302af18d007" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a3ffbf82435d-EWR", + "cf-ray": "9a8cf20fa8706e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:31 GMT", + "date": "Thu, 04 Dec 2025 17:15:24 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "380", + "openai-processing-ms": "628", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=njc6MDtQdrcZ26iMGVwB3ubObCHrz3QvBEaZhe68Z8s-1764802411945-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=InX4_raFLpPD6so5YDSanVIUeYwhE61r4XvchlbUrMI-1764868524174-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "403", + "x-envoy-upstream-service-time": "645", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -214,7 +229,7 @@ "x-ratelimit-remaining-tokens": "29999973", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_1dd8e9055e694885ab44d09d745397a8" + "x-request-id": "req_6679f034ed8847fdb661fc2177df2e81" }, "responseIsBinary": false }, @@ -235,7 +250,7 @@ "content": null, "tool_calls": [ { - "id": "call_1nCCOc7aDpJveCq0wfT7C0R3", + "id": "call_SOafgmSqA42A5VTHNCFzzclP", "type": "function", "function": { "name": "test_tool", @@ -243,7 +258,7 @@ } }, { - "id": "call_c8BDN1UNwKpc9zFvY9snVS6n", + "id": "call_vOoqWR3PM0cJycPOu020fsIB", "type": "function", "function": { "name": "test_tool", @@ -257,12 +272,12 @@ { "role": "tool", "content": "Called with 1", - "tool_call_id": "call_1nCCOc7aDpJveCq0wfT7C0R3" + "tool_call_id": "call_SOafgmSqA42A5VTHNCFzzclP" }, { "role": "tool", "content": "Called with 2", - "tool_call_id": "call_c8BDN1UNwKpc9zFvY9snVS6n" + "tool_call_id": "call_vOoqWR3PM0cJycPOu020fsIB" } ], "tools": [ @@ -272,12 +287,17 @@ "name": "test_tool", "description": "A test tool", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "count": { "type": "number" } - } + }, + "required": [ + "count" + ], + "additionalProperties": false } } } @@ -286,27 +306,27 @@ }, "status": 200, "response": [ - "1b4403001c07762c637abc12dcb8c9083da735f773c4b91062b76e1085aebea9c3a23071ae9b158d273ac0b144240fa3ceab6c5a1fc28f8f2ffcb6d91809150523986ea99e7b05d5b76f08840e4028ff66a7454275c2927d4bd6d196cb7cddab7bde825ba89ea88ecfdbd30b87808d5ccfd617243022ec8d0a8053e41ab3bcc8f1442b4951d52f1a4acca93c0d2856bd28f2c24e004078c9897d23c370b2782cd9ca9ae18360852050e549d111f81d1660ada676e6510e6a2e7de7487613c81f7881ebcbfee51f6a2634ea5bcc56bc68add51dfa5fcf8f92dc2faadcaabb2b484b45c710200165365a49926ffed8b6261a28b6282d1a1dfbf81a7082b842043a122cd19069f3ae44851c53d501d1f6a80cc8eb4e6dbb9f867b9bc928dfafd1d8f119eb1f0c33bfb6995c86a8fa84d9b6ba23cabeb98810ef69e4cfa6415d6f42b70298586801265154fd953674fe5162bfbd4277554e730551502df400" + "1b2503001c07ceb92e88a0d57588fa8962729ed0edd5236a19fcbc4ffdf2c3c0ba0f6176eab0284cddbce736271a602cdf188303eb7c2d4b2749362cee206f13cb077f574f37940600aebcf7cba6a0934c9fae3607f5c3dfd7571447d336cccef3ca7237c3e186877494302bbf2041001119bd0351d71443335449397921b9211f3703556a9aa709158c27433bc50200d2cf38e81b7a8ac33612c8a7a21a3100e6a8ab8bd686e3171840d49a5b57922cdec4fff147b9051fd795a1e2115e2e733bfb25b954d471d3d55e8f6e9478861d2540431cf9688683be1acf47259c9a252b9bc18e6e660f44599964e30a84294d7c4cd41031ad4ed2b43d5e35995e4c9bc1bd6e5f3e9eab5f0ab2370bd495bea0fcc9b48aefd52fa51430ed8a5855ba062a5e9a88956c68e4c5382fda431a76009583071032c1b4af59c3271807f61d3576688866282bb2e1a10f" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a402eb44435d-EWR", + "cf-ray": "9a8cf21439a56e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:32 GMT", + "date": "Thu, 04 Dec 2025 17:15:24 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "439", + "openai-processing-ms": "276", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=co2Kcpyfm7ogh1QQ5SAZ9JXSOXl2SJBD3B_VQbO3n5c-1764802412509-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=fk.YZ1nN6lHx9Jk384yzaRNH9.qjOCnmr57tKCKBneA-1764868524562-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "452", + "x-envoy-upstream-service-time": "294", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -314,7 +334,7 @@ "x-ratelimit-remaining-tokens": "29999963", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_52b80bc7966442caa0f3c3f87c357d91" + "x-request-id": "req_fb4e2bb27818409ea6c2bdf6d1e3a979" }, "responseIsBinary": false }, @@ -338,12 +358,17 @@ "name": "test_tool", "description": "A test tool", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "value": { "type": "string" } - } + }, + "required": [ + "value" + ], + "additionalProperties": false } } } @@ -352,35 +377,35 @@ }, "status": 200, "response": [ - "1b3404201c07762cf8856ed59074e213857a5ea1cb2baf444b2db2b3eaa77eb10e847d30da0bdc3a0a2c7d0f2e97670b2d96dbcde58f8dc9fd98d8e0291a96259c52b69948a1d27eca1874a789d1d33dbbbdfb43650290c99fc56771922be555fb3e9e666b7cffda3a5ffdc573502beeafbcfb301c6c68896ae8f90109ac21f37c06baeb589e6658ba71918fb86fe7e2215b2c97e954d6bc77195aea1f646b33e0e10c5af71268d287b28a09e86dd18d4f5b07793fc270adb03e2cf762c8900651cbe62e90fdb7162ad4fd072ab3a231ca5bfa40f052fb76e6a2e5cdd8abfd302b24161e9abe2015836c255e18938be648de253d984fe2392ccd200efe5ba4d8d9c2b37bdee2382f5eb7d98d86fca1c10be1294c1e6a92b4563a9792974e9c8b1b4777eb661da849e592f307bc952fecc569cf9c7613a773160f2af6bd3b70f43d13e33c7859b7a8443c50d9b5fd03b688ffdec837aaf056a2e3671b55b71763cf83fd893a3c07e0eaf292bf0cd386d0a2ef07cf347e4d7950534516e6fc49d51fd2a34c6f007d9470ee0b2d7a820fb51ba2ef57418ee74761e2a57e882e" + "1b3404201c07ce392f9674370bc94efe64815e55fdd411cb03dfd840a050cf2b7479e5956869eb28b0f43db8dc3fbf2db4986eb607beb7b91f131b3c45c3b28453ca361b41a33e11419d36a7a73dab77eb50ec0144f2676e5e65ec2ed1f717f5e96539cf07e5c5df5db7a7a37bfbf51d852f9f26363444510c7d400249703f9f81a86b8aa119aaa46c6823ccdb61d5b14ac9a6e994158c6353db38ffcddd9f81bf2f68dc4b20301779141390dba2a6cca60ee27e84e192617d581ec680210da296f66d53fea7ea2a90fd077a9a0a69f4ea2548ec34b8df180fb95c0e7d72c4b48058b048f8e24414d2918461082ea8037997d49565d6428b86194417eb2f42ecffc2d37bfec5b15ebc4ecbeb0dfea1c10b76e6a61035b1b5b6752e242f65655835a5d36a37ab404d4a1723eaf066b6b015a7f531ed56ad7e5e7594ec7b2dd0c4b914e342b8272a982221c8d3d5e80d5bc4ffb0e71b6578cb9389b20db33b8c91e5f1f6a4bd3d39e0eab80877c5a420b4e8f910ea262ac92f6aaa48dd6c1d67fd2175b1df00d451c4a92eb4e80d3e586e90be5f2bf20dd1f46545361c7401" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a4064fc8435d-EWR", + "cf-ray": "9a8cf216aea26e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:33 GMT", + "date": "Thu, 04 Dec 2025 17:15:25 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "470", + "openai-processing-ms": "511", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=qctelHPmKFwZxEGKa9moqi.5BiaEpb9Ex33a4SA9UD8-1764802413080-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=lIOQ2BIO9WKpMpbKLYb2RseYMGvqbZaceIA4DTRhlng-1764868525176-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "484", + "x-envoy-upstream-service-time": "531", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", "x-ratelimit-remaining-requests": "9999", - "x-ratelimit-remaining-tokens": "29999976", + "x-ratelimit-remaining-tokens": "29999975", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_f366c98e66c0448e9288f900472afbae" + "x-request-id": "req_85d8af06b7a047e8bc14caf4c00d6c1b" }, "responseIsBinary": false }, @@ -401,7 +426,7 @@ "content": null, "tool_calls": [ { - "id": "call_ifhGQgI1OpoX0yKVpI8Uo8Ez", + "id": "call_Qxn2wdqzfjakfNA8Om3ovujF", "type": "function", "function": { "name": "test_tool", @@ -415,7 +440,7 @@ { "role": "tool", "content": "Tool result", - "tool_call_id": "call_ifhGQgI1OpoX0yKVpI8Uo8Ez" + "tool_call_id": "call_Qxn2wdqzfjakfNA8Om3ovujF" } ], "tools": [ @@ -425,12 +450,17 @@ "name": "test_tool", "description": "A test tool", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "value": { "type": "string" } - } + }, + "required": [ + "value" + ], + "additionalProperties": false } } } @@ -439,27 +469,27 @@ }, "status": 200, "response": [ - "1b2303201c076eac66e4a4919313a8725ea1a6ea277ab638a7f2d1e5b1deef802465009c3a2c0a5337efb9cd99c6f2ffedc98175be96a593242c4b3815dd1093a4f20e9e1e2d8f8020c9dfc2baaba89bf7e2781c93785cfcf3784a9bdb3defdaa7dddf9b7708a341942fac7d40827886f49c77a0b44cdd164a975a8fdf1165c5b49ba8de52334da9b0e7a6d94bf60fb20f76fca3116e18c782ec945024e0bc8236b455ec80dc57f0710934aa374a9383f41b7f9c5f61b5ae653581e0d7b22e71f622b7aa36ed863618af36b33b139504e8a0460154c2cc38c0cb19835b57e57537a172a37b86b651cc62b876dc5219d688fa6594d5bc9f85e2aef365a4d056744e935cacccf563e28bb7bf4edfdb8bc82fe64d3ad68fc9fa6fa13bac436e9c29854b2448619998a4e4659cf2780082dbc0c74533b030c01a6c5de8acefa443d376023fb263c78706" + "1b5e03081c07768cb38df016ccc7f95f6b4bf5cf3bb7850ac99ac99e2162a9c0a2930a205d3ecfcd5e1c4d4a28f058c698a2e9fc8d65792f824ecf8ef814d41bf535edc897f8d71711d6250ec52abb15fbd3ceaa6d927aa328564bbfdbbcbe8e97d6f53e3ab59fbd6cb5eb319888904fdd37bc2241c5b4c8bee3bc240e59cc223fb29584ca527d79ba59e1d1eaaba5e532af1bdbda2040546364f15fe420f3129fbb2641cb4a81e11a112ec71d1fa0f22f08d2722eeb71677574d4f47cb651f1f05b7e6d445aa93cb5f85eaaa4f881a7d8416b9f00a4b29dd2290080ea5432e56d06ff6c7cb43b2e4f97637e0dc245af757913236c34c2045401a269cef71268e07439ee4f37de35e48053162907d40f409c172b0d0ac977ae678a1e6f2e58de0e3a845782e3ca513a03026afaa753b5340eb5001eae0f4b1701bdff787c38c59c8f70ed5e23514661937fad93b8fcb3877285e8c38e02a9ddc8e317de28bd53467f2f4e7ccebcca3c080396c31f" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a409db58435d-EWR", + "cf-ray": "9a8cf21a7ed76e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:33 GMT", + "date": "Thu, 04 Dec 2025 17:15:25 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "342", + "openai-processing-ms": "479", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=mkbGgtSFKFMkke2kByPwDtuVbhx0DLDoBzWnqQlafXA-1764802413537-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=qNyLPFUGXiBDkXw56Stqbq0WT1NdlcADn5_3l4Z5Hog-1764868525749-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "368", + "x-envoy-upstream-service-time": "493", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -467,7 +497,7 @@ "x-ratelimit-remaining-tokens": "29999971", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_5ed619a68f8649edab3b467e443ff656" + "x-request-id": "req_54ad70544bc24bbe9083778f9fa71eb3" }, "responseIsBinary": false }, @@ -491,6 +521,7 @@ "name": "cool_logo_getter_tool", "description": "query for a company logo", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { @@ -499,7 +530,11 @@ "minLength": 1, "maxLength": 100 } - } + }, + "required": [ + "name" + ], + "additionalProperties": false } } } @@ -508,27 +543,27 @@ }, "status": 200, "response": [ - "1b4504001c07ce393d16a9ec8a3af713a8723ea1a6ca3fd1b2953995af1eb15bee183b867ee75460d1393a35e170d0c2723b9d5bacb5d2fd77e2e2295a4cadc255aa6d26525896572923d3a8c99deed9aeaa01d30006a0fc995f36053b4a5be163d7a146b49594d371360e86f96a10d479b112a1806bd499ee091258451c7d8611754d31044911e59382c4d772dc10abd46c9e4e59c1f8686aa7148074f512805e70d0c2d3b1c07c2bcb18c38ad8111c7461c09f400a9a62fda1b91722451ac82d73ceefe38e6daf50f91f70d51ea699a4af8ce9493f7b516dcf8ee393a447d034641676c52fa663325b8a9723bae414434442ac611c12851dc66cc6ac1be6d016f03d131557b0ce0db969c5bbd72bfc9d7975c6c7bf3df20f07afb8c5be39ae526b7deb0ca3b78a3a6ebadaeba7372d494dcc9f2444a0291809e3dc07c82d1f0c7ed110663f9a6e99843892824e21170dca192f6b092d62b28519e1b16898f3ad4029e41fe5bb1772ecf188b6b5cf5b70735ac59709b544b4f017c3f90955e5d64d856ca3b3491d9822a50384442b2b2970a568e13d7da80011a1bf36181aa219ca8a6c786000" + "1b4504001c07ce393d16a9ec8a3af713a8723ea1a6ca3fd1b2459d5ebfee1028fd98375688ed12a5028bcef1f7aecf7168b1dc6e0fb1b27def3571f1140d7f96704ad966228566799532328d9adce99eddd21a300b6100ca9f05152fc5766e77469776b19db2284f0b66e1577266e919cf56f300055ca3ce74bf208155c4d16718d5b60cb4d0d4cc8b82c47332e127d160629e0e4405df2ad625052099fe09406f3868e1494f113e9565f46045ec080eba30e04f20054db1d6d0dc0b912265e29639e7d771c7b657a8fc0f54f43eb4a9375d33f511ecd1aad573357362650d4d43666157fc623a26b3a57839a24b4e314424c40c25d1e9141d28663366dd30873686e79948f985c6b93e7959cdbbd75f783bf3ea8c8f7f7be41f0e5ef1ca7d735ca556fd561f466f952ce107e61fa7572c4915ca9f4c8840453012c6b96790e7e40756f113653f9aae3a843892824e21a722e58c975595163159a58cf05894cdf96aa814f28ff2dd0b39f67844dbdae72db839ab93db845a22aaf48de1fc84aaf2e8a6bc6ca3b3933a30a053364048b4b29202578a2a3dd3870a1011fa2ba7085527d20d1d7d30" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a40cbe4b435d-EWR", + "cf-ray": "9a8cf21e1e4f6e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:34 GMT", + "date": "Thu, 04 Dec 2025 17:15:26 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "371", + "openai-processing-ms": "954", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=MGROCDuDSefvEB1ljfMdWuWBHEINxZPtWYC1UYklq34-1764802414033-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=l0u8cvI3o1.I.XRbD.N5T7Bn.pyy3BakqRsfTHR68i0-1764868526807-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "405", + "x-envoy-upstream-service-time": "977", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -536,7 +571,7 @@ "x-ratelimit-remaining-tokens": "29999973", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "0s", - "x-request-id": "req_b8a24adeb2c14592b3b24feb0bcc725d" + "x-request-id": "req_97729a7b267f411bb257ccd8c7353602" }, "responseIsBinary": false }, @@ -557,7 +592,7 @@ "content": null, "tool_calls": [ { - "id": "call_QqWLj27Q8LY7ZbfoAMXJY27f", + "id": "call_kFW2MaMSo1zcq86n1umN9f0S", "type": "function", "function": { "name": "cool_logo_getter_tool", @@ -571,7 +606,7 @@ { "role": "tool", "content": "[{\"type\":\"image_url\",\"image_url\":{\"url\":\"data:image/png;base64,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\"}}]", - "tool_call_id": "call_QqWLj27Q8LY7ZbfoAMXJY27f" + "tool_call_id": "call_kFW2MaMSo1zcq86n1umN9f0S" } ], "tools": [ @@ -581,6 +616,7 @@ "name": "cool_logo_getter_tool", "description": "query for a company logo", "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { @@ -589,7 +625,11 @@ "minLength": 1, "maxLength": 100 } - } + }, + "required": [ + "name" + ], + "additionalProperties": false } } } @@ -598,27 +638,27 @@ }, "status": 200, "response": [ - "1b2e03801c07762ce6f638928adc64849ed39afb39e25888b10a2688425f2be8b0749dba79cf6dce34963126a751e76b591871382667736d6d9535f5d32b04410ebfd6d61702a183c08dcf765a24542b2c39567d4efad126c9ffa6fcb09dcc5696d778f5b6bd100b01fb04aed2d7237064be937d84536451657991132bab20b367fde246893915a311c5aa8f26573ef8417ca2905f54184d6f014bbee14d7051233e318e61c48b4e9f6144de62e6667c5129fc4ffc1166c282ba7496dcc12aa53f9b7f355625b95f54b955b36a883a4d87085000221752027131777ab7c04271256971d3a1cd084c0551e0946384212ed1759ec642a2860dd1aa2275dde5e5315301eaa9c31cb2a2152ca84b448dd5bf5ea5b6f2b9015886992fa58df8324188035d9f16f93e6a9bf1eb135112071bfaf360cfebb7d0ad104c1f2c910b075d5fb8868d32a6c9b757e8aeca69ae200aaa0503" + "1b2e03a01c07762c637abc12dcb8c9a86da57ab319d3f8628a7b62681085aebea9c3a23075f39edb9c692c3f9b9bd3a8f3b52c8c382c4b389b6b6babaca59f7e220872f8b59efa10442e80177f73b232a527b13add968bdd28719f6bebac2ef60bfdea6d36dbf635297008cc634cbd8f472054dac73be05545d2144d16d482f5437b33285b5a2ae8102d684e7b1da5d0d807e52759ed63c366b8651c55412d88a10d4dc82f48baeef313a65183d18de036c8f41ffe142bc598ee9d3d6f609ddc3dfea0c5adb408cabab01b4e0741e7180801163014a35485fcac3d76060428af2a2b5b03d9485e2d4a22af1e3b8c708fec0a248c88112e411f4a740d8ff787cc06a68f2e6fce4946604cf7680ea7feb84673c513fbaf511e089923bd5fcfc2c0356645dac5682bba3c91267dacb98162bd6db4915703cc1e9846a2c135d6adc141865a7cfba5e169bcee8992a8d9e801" ], "rawHeaders": { "access-control-expose-headers": "X-Request-ID", "alt-svc": "h3=\":443\"; ma=86400", "cf-cache-status": "DYNAMIC", - "cf-ray": "9a86a4106afe435d-EWR", + "cf-ray": "9a8cf224bc6c6e28-EWR", "connection": "keep-alive", "content-encoding": "br", "content-type": "application/json", - "date": "Wed, 03 Dec 2025 22:53:34 GMT", + "date": "Thu, 04 Dec 2025 17:15:27 GMT", "openai-organization": "stainless-lo3pdl", - "openai-processing-ms": "390", + "openai-processing-ms": "398", "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", "openai-version": "2020-10-01", "server": "cloudflare", - "set-cookie": "_cfuvid=GikF6GLf6kCnkR63rxdTSYYW7veAC4neKH6O0aUOC_M-1764802414640-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "set-cookie": "_cfuvid=LOvRoAWCrQ6T5M3T5_CH7YLU854JepQKfWzlSncIces-1764868527317-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", "strict-transport-security": "max-age=31536000; includeSubDomains; preload", "transfer-encoding": "chunked", "x-content-type-options": "nosniff", - "x-envoy-upstream-service-time": "407", + "x-envoy-upstream-service-time": "418", "x-openai-proxy-wasm": "v0.1", "x-ratelimit-limit-requests": "10000", "x-ratelimit-limit-tokens": "30000000", @@ -626,7 +666,77 @@ "x-ratelimit-remaining-tokens": "29987343", "x-ratelimit-reset-requests": "6ms", "x-ratelimit-reset-tokens": "25ms", - "x-request-id": "req_2ec3cfb9dd6c44f890f42034ca05d4b0" + "x-request-id": "req_8d58af50dc1b4c32853fe9a53a2a76d1" + }, + "responseIsBinary": false + }, + { + "scope": "https://api.openai.com:443", + "method": "POST", + "path": "/v1/chat/completions", + "body": { + "model": "gpt-4o", + "max_tokens": 1000, + "messages": [ + { + "role": "user", + "content": "Use the array_tool with the array [\"hello\", \"world\"], then provide a final response that includes the word 'foo'." + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "array_tool", + "description": "Tool for array operations", + "parameters": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "description": "Array of strings", + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "stream": false + }, + "status": 400, + "response": { + "error": { + "message": "Invalid schema for function 'array_tool': schema must be a JSON Schema of 'type: \"object\"', got 'type: \"array\"'.", + "type": "invalid_request_error", + "param": "tools[0].function.parameters", + "code": "invalid_function_parameters" + } + }, + "rawHeaders": { + "access-control-expose-headers": "X-Request-ID", + "alt-svc": "h3=\":443\"; ma=86400", + "cf-cache-status": "DYNAMIC", + "cf-ray": "9a8cf2284c9f6e28-EWR", + "connection": "keep-alive", + "content-length": "279", + "content-type": "application/json", + "date": "Thu, 04 Dec 2025 17:15:27 GMT", + "openai-organization": "stainless-lo3pdl", + "openai-processing-ms": "13", + "openai-project": "proj_FSQrMfywhpvjH41RhwSodie7", + "openai-version": "2020-10-01", + "server": "cloudflare", + "set-cookie": "_cfuvid=yaovjnUKaiTMtUADfGnuZOBaRER36255ThgNEffXMOQ-1764868527488-0.0.1.1-604800000; path=/; domain=.api.openai.com; HttpOnly; Secure; SameSite=None", + "strict-transport-security": "max-age=31536000; includeSubDomains; preload", + "x-content-type-options": "nosniff", + "x-envoy-upstream-service-time": "29", + "x-openai-proxy-wasm": "v0.1", + "x-ratelimit-limit-requests": "10000", + "x-ratelimit-limit-tokens": "30000000", + "x-ratelimit-remaining-requests": "9999", + "x-ratelimit-remaining-tokens": "29999969", + "x-ratelimit-reset-requests": "6ms", + "x-ratelimit-reset-tokens": "0s", + "x-request-id": "req_6c49242948f64e559435a8b58c423b3f" }, "responseIsBinary": false } From d75a202d030fb61491e5e92f50c7c30959c43427 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 12:19:17 -0500 Subject: [PATCH 33/43] rename BetaRunnableTool --- src/helpers/beta/json-schema.ts | 4 ++-- src/helpers/beta/zod.ts | 4 ++-- src/lib/beta/BetaRunnableTool.ts | 6 +++--- src/lib/beta/BetaToolRunner.ts | 13 ++++++++----- tests/lib/tools/BetaToolRunner.test.ts | 13 ++++++------- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/helpers/beta/json-schema.ts b/src/helpers/beta/json-schema.ts index a6c85fb0e..f3b0fc25f 100644 --- a/src/helpers/beta/json-schema.ts +++ b/src/helpers/beta/json-schema.ts @@ -1,5 +1,5 @@ import type { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; +import type { BetaRunnableChatCompletionFunctionTool, Promisable } from '../../lib/beta/BetaRunnableTool'; import type { FunctionTool } from '../../resources/beta'; import { OpenAIError } from '../../error'; @@ -15,7 +15,7 @@ export function betaTool & { t inputSchema: Schema; description: string; run: (args: NoInfer>) => Promisable>; -}): BetaRunnableTool>> { +}): BetaRunnableChatCompletionFunctionTool>> { if (options.inputSchema.type !== 'object') { throw new OpenAIError( `JSON schema for tool "${options.name}" must be an object, but got ${options.inputSchema.type}`, diff --git a/src/helpers/beta/zod.ts b/src/helpers/beta/zod.ts index 9d34addaa..d776f0c80 100644 --- a/src/helpers/beta/zod.ts +++ b/src/helpers/beta/zod.ts @@ -1,6 +1,6 @@ import type { infer as zodInfer, ZodType } from 'zod/v4'; import * as z from 'zod/v4'; -import type { BetaRunnableTool, Promisable } from '../../lib/beta/BetaRunnableTool'; +import type { BetaRunnableChatCompletionFunctionTool, Promisable } from '../../lib/beta/BetaRunnableTool'; import type { ChatCompletionContentPart } from '../../resources'; /** @@ -14,7 +14,7 @@ export function betaZodFunctionTool(options: { parameters: InputSchema; description: string; run: (args: zodInfer) => Promisable; -}): BetaRunnableTool> { +}): BetaRunnableChatCompletionFunctionTool> { const jsonSchema = z.toJSONSchema(options.parameters, { reused: 'ref' }); return { diff --git a/src/lib/beta/BetaRunnableTool.ts b/src/lib/beta/BetaRunnableTool.ts index 8479bcbf4..21888a006 100644 --- a/src/lib/beta/BetaRunnableTool.ts +++ b/src/lib/beta/BetaRunnableTool.ts @@ -1,10 +1,10 @@ -import type { ChatCompletionContentPart, ChatCompletionTool } from '../../resources'; +import type { ChatCompletionContentPart, ChatCompletionFunctionTool } from '../../resources'; export type Promisable = T | Promise; -// this type is just an extension of BetaTool with a run and parse method +// this type is just an extension of ChatCompletionFunctionTool with a run and parse method // that will be called by `toolRunner()` helpers -export type BetaRunnableTool = ChatCompletionTool & { +export type BetaRunnableChatCompletionFunctionTool = ChatCompletionFunctionTool & { run: (args: Input) => Promisable; parse: (content: unknown) => Input; }; diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index e91ae4a41..5bb7dacd0 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -11,7 +11,7 @@ import type { ChatCompletionTool, ChatCompletionToolMessageParam, } from '../../resources/chat/completions'; -import type { BetaRunnableTool } from './BetaRunnableTool'; +import type { BetaRunnableChatCompletionFunctionTool } from './BetaRunnableTool'; /** * Just Promise.withResolvers(), which is not available in all environments. @@ -255,7 +255,10 @@ export class BetaToolRunner } const toolsResponse = generateToolResponse( lastMessage, - this.#state.params.tools.filter((tool): tool is BetaRunnableTool => 'run' in tool), + this.#state.params.tools.filter( + (tool): tool is BetaRunnableChatCompletionFunctionTool => + 'run' in tool && tool.type === 'function', + ), ); this.#toolResponse = toolsResponse; return toolsResponse; @@ -358,7 +361,7 @@ export class BetaToolRunner async function generateToolResponse( lastMessage: ChatCompletionMessage, - tools: BetaRunnableTool[], + tools: BetaRunnableChatCompletionFunctionTool[], ): Promise { // Only process if the last message is from the assistant and has tool use blocks if ( @@ -383,7 +386,7 @@ async function generateToolResponse( const tool = tools.find( (t) => t.type === 'function' && toolUse.function.name === t.function.name, - ) as BetaRunnableTool; + ) as BetaRunnableChatCompletionFunctionTool; if (!tool || !('run' in tool)) { return { @@ -435,7 +438,7 @@ type Simplify = { [KeyType in keyof T]: T[KeyType] } & {}; */ export type BetaToolRunnerParams = Simplify< Omit & { - tools: (ChatCompletionTool | BetaRunnableTool)[]; + tools: (ChatCompletionTool | BetaRunnableChatCompletionFunctionTool)[]; /** * Maximum number of iterations (API requests) to make in the tool execution loop. * Each iteration consists of: assistant response → tool execution → tool results. diff --git a/tests/lib/tools/BetaToolRunner.test.ts b/tests/lib/tools/BetaToolRunner.test.ts index 04c53dcdb..5018242ec 100644 --- a/tests/lib/tools/BetaToolRunner.test.ts +++ b/tests/lib/tools/BetaToolRunner.test.ts @@ -1,6 +1,6 @@ import OpenAI from 'openai'; import { mockFetch } from '../../utils/mock-fetch'; -import type { BetaRunnableTool } from 'openai/lib/beta/BetaRunnableTool'; +import type { BetaRunnableChatCompletionFunctionTool } from 'openai/lib/beta/BetaRunnableTool'; import type { ChatCompletion, ChatCompletionChunk, @@ -11,9 +11,8 @@ import type { } from 'openai/resources'; import type { Fetch } from 'openai/internal/builtin-types'; import type { BetaToolRunnerParams } from 'openai/lib/beta/BetaToolRunner'; -import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; -const weatherTool: BetaRunnableTool<{ location: string }> = { +const weatherTool: BetaRunnableChatCompletionFunctionTool<{ location: string }> = { type: 'function', function: { name: 'getWeather', @@ -29,7 +28,7 @@ const weatherTool: BetaRunnableTool<{ location: string }> = { parse: (input: unknown) => input as { location: string }, }; -const calculatorTool: BetaRunnableTool<{ a: number; b: number; operation: string }> = { +const calculatorTool: BetaRunnableChatCompletionFunctionTool<{ a: number; b: number; operation: string }> = { type: 'function', function: { name: 'calculate', @@ -766,7 +765,7 @@ describe('ToolRunner', () => { }); it('handles tool execution errors', async () => { - const errorTool: BetaRunnableTool<{ shouldFail: boolean }> = { + const errorTool: BetaRunnableChatCompletionFunctionTool<{ shouldFail: boolean }> = { type: 'function', function: { name: 'errorTool', @@ -1010,7 +1009,7 @@ describe('ToolRunner', () => { }); it('allows you to use non-string returning custom tools', async () => { - const customTool: BetaRunnableTool<{ location: string }> = { + const customTool: BetaRunnableChatCompletionFunctionTool<{ location: string }> = { type: 'function', function: { name: 'getWeather', @@ -1140,7 +1139,7 @@ describe('ToolRunner', () => { it('calls tools at most once', async () => { let weatherToolCallCount = 0; - const trackingWeatherTool: BetaRunnableTool<{ location: string }> = { + const trackingWeatherTool: BetaRunnableChatCompletionFunctionTool<{ location: string }> = { type: 'function', function: { name: 'getWeather', From 3c8bdba6c1d75e5496ed933687b3593cda66c472 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 12:32:22 -0500 Subject: [PATCH 34/43] Solve more TODOs --- src/lib/beta/BetaToolRunner.ts | 28 +++--------- tests/lib/tools/BetaToolRunner.test.ts | 62 ++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 21 deletions(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 5bb7dacd0..57b6dc32c 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -96,9 +96,7 @@ export class BetaToolRunner } async *[Symbol.asyncIterator](): AsyncIterator< - Stream extends true ? - ChatCompletionStream // TODO: for now! - : ChatCompletion + Stream extends true ? ChatCompletionStream : ChatCompletion > { if (this.#consumed) { throw new OpenAIError('Cannot iterate over a consumed stream'); @@ -241,7 +239,7 @@ export class BetaToolRunner * } */ async generateToolResponse() { - // The most recent message from the assistant. TODO: do we want || this.params.messages.at(-1)? + // The most recent message from the assistant. const message = await this.#message; if (!message) { return null; @@ -281,7 +279,7 @@ export class BetaToolRunner * console.log('Final response:', finalMessage.content); */ done(): Promise { - return this.#completion.promise; // TODO: find a more type safe way to do this + return this.#completion.promise; } /** @@ -351,7 +349,7 @@ export class BetaToolRunner * Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone() * This allows using `await runner` instead of `await runner.runUntilDone()` */ - then( // TODO: make sure these types are OK + then( onfulfilled?: ((value: ChatCompletionMessage) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null, ): Promise { @@ -364,12 +362,7 @@ async function generateToolResponse( tools: BetaRunnableChatCompletionFunctionTool[], ): Promise { // Only process if the last message is from the assistant and has tool use blocks - if ( - !lastMessage || - lastMessage.role !== 'assistant' || - // !lastMessage.content || TODO: openai doesn't give content at the same time. ensure this is really always true though - typeof lastMessage.content === 'string' - ) { + if (!lastMessage || lastMessage.role !== 'assistant' || typeof lastMessage.content === 'string') { return null; } @@ -382,7 +375,7 @@ async function generateToolResponse( return ( await Promise.all( prevToolCalls.map(async (toolUse) => { - if (toolUse.type !== 'function') return; // TODO: what about other calls? + if (toolUse.type !== 'function') return; // TODO: eventually we should support additional tool call types const tool = tools.find( (t) => t.type === 'function' && toolUse.function.name === t.function.name, @@ -398,14 +391,7 @@ async function generateToolResponse( } try { - let input = toolUse.function.arguments; - // TODO: is this always safe? - if (typeof input === 'string') { - input = JSON.parse(input); - } - input = tool.parse(input); - - const result = await tool.run(input); + const result = await tool.run(tool.parse(JSON.parse(toolUse.function.arguments))); return { type: 'tool_result' as const, tool_call_id: toolUse.id, diff --git a/tests/lib/tools/BetaToolRunner.test.ts b/tests/lib/tools/BetaToolRunner.test.ts index 5018242ec..b244c6437 100644 --- a/tests/lib/tools/BetaToolRunner.test.ts +++ b/tests/lib/tools/BetaToolRunner.test.ts @@ -11,6 +11,7 @@ import type { } from 'openai/resources'; import type { Fetch } from 'openai/internal/builtin-types'; import type { BetaToolRunnerParams } from 'openai/lib/beta/BetaToolRunner'; +import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; const weatherTool: BetaRunnableChatCompletionFunctionTool<{ location: string }> = { type: 'function', @@ -1202,4 +1203,65 @@ describe('ToolRunner', () => { await expectDone(iterator); }); }); + + it('caches tool responses properly and handles text messages', async () => { + let callCount = 0; + + const { runner, handleAssistantMessage } = setupTest({ + messages: [{ role: 'user', content: 'What is the weather?' }], + tools: [ + { + type: 'function', + function: { + name: 'getWeather', + description: 'Get weather information', + parameters: { + type: 'object', + properties: { + location: { + type: 'string', + description: 'The location to get weather information for', + }, + }, + }, + }, + run: async ({ location }: { location: string }) => { + callCount++; + return `Sunny in ${location}`; + }, + parse: (input: unknown) => input as { location: string }, + }, + ], + }); + + const iterator = runner[Symbol.asyncIterator](); + + // Initial tool response should be null (no assistant message yet) + const initialResponse = await runner.generateToolResponse(); + expect(initialResponse).toBeNull(); + expect(callCount).toBe(0); + + // Assistant requests weather tool + handleAssistantMessage([getWeatherToolUse('Paris')]); + await iterator.next(); + + // Tool response should be cached + const toolResponse1 = await runner.generateToolResponse(); + expect(toolResponse1).toMatchObject([getWeatherToolResult('Paris')]); + expect(callCount).toBe(1); + + const toolResponse2 = await runner.generateToolResponse(); + expect(toolResponse2).toMatchObject([getWeatherToolResult('Paris')]); + expect(callCount).toBe(1); // Still 1 - cached response + + // Now test with a text message + handleAssistantMessage(getTextContent()); + await iterator.next(); + + const textResponse = await runner.generateToolResponse(); + expect(textResponse).toBeNull(); // Text messages return null + expect(callCount).toBe(1); // Still 1 - no new tool calls + + await expectDone(iterator); + }); }); From 1066d3027d64d13ca9cd3f603bdd22353008e780 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 13:04:02 -0500 Subject: [PATCH 35/43] add doc --- src/resources/beta/chat.ts | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/resources/beta/chat.ts b/src/resources/beta/chat.ts index 980884337..af9ebee4b 100644 --- a/src/resources/beta/chat.ts +++ b/src/resources/beta/chat.ts @@ -6,6 +6,39 @@ import { } from '../../lib/beta/BetaToolRunner'; export class BetaCompletions extends APIResource { + /** + * Creates a tool runner that automates the back-and-forth conversation between the model and tools. + * + * The tool runner handles the following workflow: + * 1. Sends a request to the model with some initial messages and available tools + * 2. If the model calls tools, executes them automatically + * 3. Sends tool results back to the model + * 4. Repeats until the model provides a final response or max_iterations is reached + * + * @see [helpers.md](https://github.com/openai/openai-node/blob/master/helpers.md) + * + * @example + * ```typescript + * const finalMessage = await client.beta.chat.completions.toolRunner({ + * messages: [{ role: 'user', content: 'What's the weather in San Francisco?' }], + * tools: [ + * betaZodFunctionTool({ + * name: 'get_weather', + * inputSchema: z.object({ + * location: z.string().describe('The city and state, e.g. San Francisco, CA'), + * unit: z.enum(['celsius', 'fahrenheit']).default('fahrenheit'), + * }), + * description: 'Get the current weather in a given location', + * run: async (input) => { + * return `The weather in ${input.location} is ${input.unit === 'celsius' ? '22°C' : '72°F'}`; + * }, + * }) + * ], + * model: 'gpt-4o' + * }); + * console.log(finalMessage.content); + * ``` + */ toolRunner( body: BetaToolRunnerParams & { stream?: false }, options?: BetaToolRunnerRequestOptions, @@ -14,7 +47,6 @@ export class BetaCompletions extends APIResource { body: BetaToolRunnerParams & { stream: true }, options?: BetaToolRunnerRequestOptions, ): BetaToolRunner; - toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner; toolRunner(body: BetaToolRunnerParams, options?: BetaToolRunnerRequestOptions): BetaToolRunner { return new BetaToolRunner(this._client, body, options); } From b0f88180690db8f1fb1eea8a37dc88383c63de93 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 13:30:33 -0500 Subject: [PATCH 36/43] improve names --- examples/tool-helpers-json-schema.ts | 4 ++-- src/helpers/beta/json-schema.ts | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/tool-helpers-json-schema.ts b/examples/tool-helpers-json-schema.ts index 5c602830c..6f67ae707 100755 --- a/examples/tool-helpers-json-schema.ts +++ b/examples/tool-helpers-json-schema.ts @@ -1,7 +1,7 @@ #!/usr/bin/env -S npm run tsn -T import OpenAI from 'openai'; -import { betaTool } from 'openai/helpers/beta/json-schema'; +import { betaFunctionTool } from 'openai/helpers/beta/json-schema'; const client = new OpenAI(); @@ -14,7 +14,7 @@ async function main() { }, ], tools: [ - betaTool({ + betaFunctionTool({ name: 'getWeather', description: 'Get the weather at a specific location', inputSchema: { diff --git a/src/helpers/beta/json-schema.ts b/src/helpers/beta/json-schema.ts index f3b0fc25f..53185c3d5 100644 --- a/src/helpers/beta/json-schema.ts +++ b/src/helpers/beta/json-schema.ts @@ -10,7 +10,9 @@ type NoInfer = T extends infer R ? R : never; * to the `.toolRunner()` method. The schema is used to automatically validate * the input arguments for the tool. */ -export function betaTool & { type: 'object' }>(options: { +export function betaFunctionTool< + const Schema extends Exclude & { type: 'object' }, +>(options: { name: string; inputSchema: Schema; description: string; From 8eb6c3d1bdabd4c0f1962de93594038bf7bb1ce3 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 13:33:44 -0500 Subject: [PATCH 37/43] remove debugging --- examples/debugging.ts | 57 ------------------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 examples/debugging.ts diff --git a/examples/debugging.ts b/examples/debugging.ts deleted file mode 100644 index 51ae5ebfe..000000000 --- a/examples/debugging.ts +++ /dev/null @@ -1,57 +0,0 @@ -import OpenAI from 'openai'; - import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; - import { z } from 'zod'; - - const client = new OpenAI(); - - async function main() { - // Define the schema using oneOf - const searchSchema = z.object({ - searchCriteria: z.object({ - // This creates a oneOf in the JSON Schema - criteria: z.union([ - z.object({ - name: z.string().describe('Search by name'), - type: z.enum(['person', 'product', 'location']).describe('Type of entity to search for') - }), - z.object({ - id: z.number().describe('Search by numeric ID'), - includeDeleted: z.boolean().optional().describe('Whether to include deleted items') - }) - ]) - }) - }); - - const message = await client.beta.chat.completions.toolRunner({ - messages: [ - { - role: 'user', - content: `I need to search for something. You can search by either name or ID.`, - }, - ], - tools: [ - betaZodFunctionTool({ - name: 'searchDatabase', - description: 'Search database for items by either name or ID', - parameters: searchSchema, - run: (params) => { - const criteria = params.searchCriteria.criteria; - - if ('name' in criteria) { - return `Found 3 results for name "${criteria.name}" of type "${criteria.type}"`; - } else { - const deletedStatus = criteria.includeDeleted ? ' (including deleted items)' : ''; - return `Found item with ID ${criteria.id}${deletedStatus}`; - } - }, - }), - ], - model: 'gpt-4o', - max_tokens: 1024, - max_iterations: 10, - }); - - console.log('Final response:', message.content); - } - - main(); From 949d8a002a491ffd1447303dc3df6a86c6b9c064 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Thu, 4 Dec 2025 13:46:43 -0500 Subject: [PATCH 38/43] fix more naming --- src/lib/beta/BetaToolRunner.ts | 30 ++++++++++++++------------ tests/lib/tools/BetaToolRunner.test.ts | 6 +++--- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 57b6dc32c..2ed9a3624 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -31,10 +31,10 @@ function promiseWithResolvers(): { } /** - * A BetaToolRunner handles the automatic conversation loop between the assistant and tools. + * A `BetaToolRunner` handles the automatic conversation loop between the assistant and tools. * - * A BetaToolRunner is an async iterable that yields either ChatCompletion or - * ChatCompletionStream objects depending on the streaming configuration. + * A `BetaToolRunner` is an async iterable that yields either `ChatCompletion` or + * `ChatCompletionStream` objects depending on the streaming configuration. */ export class BetaToolRunner implements AsyncIterable @@ -230,7 +230,7 @@ export class BetaToolRunner * Get the tool response for the last message from the assistant. * Avoids redundant tool executions by caching results. * - * @returns A promise that resolves to a BetaMessageParam containing tool results, or null if no tools need to be executed + * @returns A promise that resolves to a `ChatCompletionToolMessageParam` containing tool results, or null if no tools need to be executed * * @example * const toolResponse = await runner.generateToolResponse(); @@ -238,7 +238,7 @@ export class BetaToolRunner * console.log('Tool results:', toolResponse.content); * } */ - async generateToolResponse() { + async generateToolResponse(): Promise { // The most recent message from the assistant. const message = await this.#message; if (!message) { @@ -266,7 +266,7 @@ export class BetaToolRunner * Wait for the async iterator to complete. This works even if the async iterator hasn't yet started, and * will wait for an instance to start and go to completion. * - * @returns A promise that resolves to the final BetaMessage when the iterator completes + * @returns A promise that resolves to the final `ChatComletionMessage` when the iterator completes * * @example * // Start consuming the iterator @@ -283,12 +283,14 @@ export class BetaToolRunner } /** - * Returns a promise indicating that the stream is done. Unlike .done(), this will eagerly read the stream: - * * If the iterator has not been consumed, consume the entire iterator and return the final message from the - * assistant. - * * If the iterator has been consumed, waits for it to complete and returns the final message. + * Returns a promise indicating that the stream is done. Unlike .done(), this + * will eagerly read the stream: * - * @returns A promise that resolves to the final BetaMessage from the conversation + * - If the iterator has not been consumed, consume the entire iterator and + * return the final message from the assistant. + * - If the iterator has been consumed, waits for it to complete and returns the final message. + * + * @returns A promise that resolves to the final `ChatCompletionMessage` from the conversation * @throws {OpenAIError} If no messages were processed during the conversation * * @example @@ -308,9 +310,9 @@ export class BetaToolRunner } /** - * Get the current parameters being used by the ToolRunner. + * Get the current parameters being used by the `BetaToolRunner`. * - * @returns A readonly view of the current ToolRunnerParams + * @returns A readonly view of the current `BetaToolRunnerParams` * * @example * const currentParams = runner.params; @@ -324,7 +326,7 @@ export class BetaToolRunner /** * Add one or more messages to the conversation history. * - * @param messages - One or more BetaMessageParam objects to add to the conversation + * @param messages - One or more `ChatCompletionMessageParam` objects to add to the conversation * * @example * runner.pushMessages( diff --git a/tests/lib/tools/BetaToolRunner.test.ts b/tests/lib/tools/BetaToolRunner.test.ts index b244c6437..f466fc63a 100644 --- a/tests/lib/tools/BetaToolRunner.test.ts +++ b/tests/lib/tools/BetaToolRunner.test.ts @@ -112,7 +112,7 @@ function getTextContent(text?: string): ChatCompletionMessage { }; } -function betaMessageToStreamEvents(message: ChatCompletion): ChatCompletionChunk[] { +function chunkChatCompletion(message: ChatCompletion): ChatCompletionChunk[] { const events: ChatCompletionChunk[] = []; const messageContent = message.choices[0]!.message; @@ -374,7 +374,7 @@ function setupTest(params: Partial = {}): SetupTestResult< }, }; - handleStreamEvents(betaMessageToStreamEvents(message)); + handleStreamEvents(chunkChatCompletion(message)); return message; }; @@ -459,7 +459,7 @@ describe('ToolRunner', () => { await expectDone(iterator); }); - it('yields BetaMessageStream when stream=true', async () => { + it('yields ChatCompletionStream when stream=true', async () => { const { runner, handleAssistantMessageStream } = setupTest({ stream: true }); const iterator = runner[Symbol.asyncIterator](); From 20f39a57c0e95953041feb0504e26274cd9a44d8 Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Fri, 5 Dec 2025 10:00:01 -0500 Subject: [PATCH 39/43] rename to parameters --- examples/tool-helpers-json-schema.ts | 2 +- src/helpers/beta/json-schema.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/tool-helpers-json-schema.ts b/examples/tool-helpers-json-schema.ts index 6f67ae707..aef9bd52f 100755 --- a/examples/tool-helpers-json-schema.ts +++ b/examples/tool-helpers-json-schema.ts @@ -17,7 +17,7 @@ async function main() { betaFunctionTool({ name: 'getWeather', description: 'Get the weather at a specific location', - inputSchema: { + parameters: { type: 'object', properties: { location: { diff --git a/src/helpers/beta/json-schema.ts b/src/helpers/beta/json-schema.ts index 53185c3d5..4e6630b35 100644 --- a/src/helpers/beta/json-schema.ts +++ b/src/helpers/beta/json-schema.ts @@ -14,13 +14,13 @@ export function betaFunctionTool< const Schema extends Exclude & { type: 'object' }, >(options: { name: string; - inputSchema: Schema; + parameters: Schema; description: string; run: (args: NoInfer>) => Promisable>; }): BetaRunnableChatCompletionFunctionTool>> { - if (options.inputSchema.type !== 'object') { + if (options.parameters.type !== 'object') { throw new OpenAIError( - `JSON schema for tool "${options.name}" must be an object, but got ${options.inputSchema.type}`, + `JSON schema for tool "${options.name}" must be an object, but got ${options.parameters.type}`, ); } @@ -28,7 +28,7 @@ export function betaFunctionTool< type: 'function', function: { name: options.name, - parameters: options.inputSchema, + parameters: options.parameters, description: options.description, }, run: options.run, From ec31a58921eb68c5bdb16b5ce235f6d43e316bfa Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Fri, 5 Dec 2025 10:00:27 -0500 Subject: [PATCH 40/43] allow object --- src/helpers/beta/json-schema.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/helpers/beta/json-schema.ts b/src/helpers/beta/json-schema.ts index 4e6630b35..35af1d313 100644 --- a/src/helpers/beta/json-schema.ts +++ b/src/helpers/beta/json-schema.ts @@ -1,7 +1,6 @@ import type { FromSchema, JSONSchema } from 'json-schema-to-ts'; import type { BetaRunnableChatCompletionFunctionTool, Promisable } from '../../lib/beta/BetaRunnableTool'; import type { FunctionTool } from '../../resources/beta'; -import { OpenAIError } from '../../error'; type NoInfer = T extends infer R ? R : never; @@ -18,12 +17,6 @@ export function betaFunctionTool< description: string; run: (args: NoInfer>) => Promisable>; }): BetaRunnableChatCompletionFunctionTool>> { - if (options.parameters.type !== 'object') { - throw new OpenAIError( - `JSON schema for tool "${options.name}" must be an object, but got ${options.parameters.type}`, - ); - } - return { type: 'function', function: { From ded0bd1937fd0572faa798e1955bd443c7b3087b Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Fri, 5 Dec 2025 13:21:22 -0500 Subject: [PATCH 41/43] make linter happy --- tests/lib/tools/BetaToolRunner.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/lib/tools/BetaToolRunner.test.ts b/tests/lib/tools/BetaToolRunner.test.ts index f466fc63a..da49cad6c 100644 --- a/tests/lib/tools/BetaToolRunner.test.ts +++ b/tests/lib/tools/BetaToolRunner.test.ts @@ -11,7 +11,6 @@ import type { } from 'openai/resources'; import type { Fetch } from 'openai/internal/builtin-types'; import type { BetaToolRunnerParams } from 'openai/lib/beta/BetaToolRunner'; -import { betaZodFunctionTool } from 'openai/helpers/beta/zod'; const weatherTool: BetaRunnableChatCompletionFunctionTool<{ location: string }> = { type: 'function', From ac91ad0b6f7b5ea7ae812ef1303024df0799439f Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Fri, 5 Dec 2025 15:05:12 -0500 Subject: [PATCH 42/43] clean up --- src/lib/beta/BetaToolRunner.ts | 72 ++++++++++++++++------------------ 1 file changed, 33 insertions(+), 39 deletions(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index 2ed9a3624..bb25f192d 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -361,7 +361,7 @@ export class BetaToolRunner async function generateToolResponse( lastMessage: ChatCompletionMessage, - tools: BetaRunnableChatCompletionFunctionTool[], + tools: BetaRunnableChatCompletionFunctionTool[], ): Promise { // Only process if the last message is from the assistant and has tool use blocks if (!lastMessage || lastMessage.role !== 'assistant' || typeof lastMessage.content === 'string') { @@ -376,46 +376,40 @@ async function generateToolResponse( return ( await Promise.all( - prevToolCalls.map(async (toolUse) => { - if (toolUse.type !== 'function') return; // TODO: eventually we should support additional tool call types - - const tool = tools.find( - (t) => t.type === 'function' && toolUse.function.name === t.function.name, - ) as BetaRunnableChatCompletionFunctionTool; - - if (!tool || !('run' in tool)) { - return { - type: 'tool_result' as const, - tool_call_id: toolUse.id, - content: `Error: Tool '${toolUse.function.name}' not found`, - is_error: true, - }; - } + prevToolCalls.map( + async (toolUse): Promise => { + if (toolUse.type !== 'function') return null; // TODO: eventually we should support additional tool call types + + const tool = tools.find( + (t) => t.type === 'function' && toolUse.function.name === t.function.name, + ) as BetaRunnableChatCompletionFunctionTool; + + if (!tool || !('run' in tool)) { + return { + role: 'tool', + tool_call_id: toolUse.id, + content: `Error: Tool '${toolUse.function.name}' not found`, + }; + } - try { - const result = await tool.run(tool.parse(JSON.parse(toolUse.function.arguments))); - return { - type: 'tool_result' as const, - tool_call_id: toolUse.id, - content: typeof result === 'string' ? result : JSON.stringify(result), - }; - } catch (error) { - return { - type: 'tool_result' as const, - tool_call_id: toolUse.id, - content: `Error: ${error instanceof Error ? error.message : String(error)}`, - is_error: true, - }; - } - }), + try { + const result = await tool.run(tool.parse(JSON.parse(toolUse.function.arguments))); + return { + role: 'tool', + tool_call_id: toolUse.id, + content: typeof result === 'string' ? result : JSON.stringify(result), + }; + } catch (error) { + return { + role: 'tool', + tool_call_id: toolUse.id, + content: `Error: ${error instanceof Error ? error.message : String(error)}`, + }; + } + }, + ), ) - ) - .filter((result): result is NonNullable => result != null) - .map((toolResult) => ({ - role: 'tool' as const, - content: toolResult.content, - tool_call_id: toolResult.tool_call_id, - })); + ).filter((result): result is NonNullable => result != null); } // vendored from typefest just to make things look a bit nicer on hover From c0a0bb0ffe93cc7a8a80dbaa3866ba7e8aa23ebf Mon Sep 17 00:00:00 2001 From: Wolf Mermelstein Date: Fri, 5 Dec 2025 15:07:20 -0500 Subject: [PATCH 43/43] change anys to unknowns --- src/lib/beta/BetaToolRunner.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/beta/BetaToolRunner.ts b/src/lib/beta/BetaToolRunner.ts index bb25f192d..4e6a0f379 100644 --- a/src/lib/beta/BetaToolRunner.ts +++ b/src/lib/beta/BetaToolRunner.ts @@ -254,7 +254,7 @@ export class BetaToolRunner const toolsResponse = generateToolResponse( lastMessage, this.#state.params.tools.filter( - (tool): tool is BetaRunnableChatCompletionFunctionTool => + (tool): tool is BetaRunnableChatCompletionFunctionTool => 'run' in tool && tool.type === 'function', ), ); @@ -420,7 +420,7 @@ type Simplify = { [KeyType in keyof T]: T[KeyType] } & {}; */ export type BetaToolRunnerParams = Simplify< Omit & { - tools: (ChatCompletionTool | BetaRunnableChatCompletionFunctionTool)[]; + tools: (ChatCompletionTool | BetaRunnableChatCompletionFunctionTool)[]; /** * Maximum number of iterations (API requests) to make in the tool execution loop. * Each iteration consists of: assistant response → tool execution → tool results.