@singlestore/ai
Advanced tools
Comparing version 0.0.27 to 0.0.28
@@ -1,122 +0,9 @@ | ||
import z$1, { z } from 'zod'; | ||
import { ChatCompletionMessageParam } from 'openai/resources/chat/completions'; | ||
import { OpenAI } from 'openai'; | ||
import { ChatCompletionCreateParamsBase } from 'openai/resources/chat/completions.mjs'; | ||
import { EmbeddingCreateParams } from 'openai/resources/embeddings'; | ||
import { AnyChatCompletionTool, ChatCompletionsManager, OpenAIChatCompletions } from './chat-completions/index.js'; | ||
import { EmbeddingsManager, OpenAIEmbeddingsManager } from './embeddings.js'; | ||
import 'openai/resources/chat/completions'; | ||
import 'zod'; | ||
import 'openai'; | ||
import 'openai/resources/chat/completions.mjs'; | ||
import 'openai/resources/embeddings'; | ||
interface ChatCompletion { | ||
content: string; | ||
} | ||
type ChatCompletionStream = AsyncGenerator<ChatCompletion>; | ||
type OnChatCompletionChunk = (chunk: ChatCompletion) => Promise<void> | void; | ||
interface ChatCompletionMessage { | ||
role: Extract<ChatCompletionMessageParam["role"], "system" | "assistant" | "user">; | ||
content: string | null; | ||
} | ||
type ChatCompletionToolCall<T extends string, U extends z.AnyZodObject | undefined, K> = (params: U extends z.AnyZodObject ? z.infer<U> : void) => Promise<{ | ||
name: T; | ||
value: K; | ||
params?: U extends z.AnyZodObject ? z.infer<U> : undefined; | ||
}>; | ||
interface ChatCompletionToolConfig<T extends string, U extends z.AnyZodObject | undefined, K extends ChatCompletionToolCall<T, U, any>> { | ||
name: T; | ||
description: string; | ||
params?: U; | ||
call: K; | ||
} | ||
type AnyChatCompletionTool = ChatCompletionTool<string, z.AnyZodObject | undefined, ChatCompletionToolCall<string, any | undefined, any>>; | ||
type MergeChatCompletionTools<T extends AnyChatCompletionTool[] | undefined, U extends AnyChatCompletionTool[] | undefined> = T extends AnyChatCompletionTool[] ? U extends AnyChatCompletionTool[] ? [...T, ...U] : T : U extends AnyChatCompletionTool[] ? U : undefined; | ||
declare class ChatCompletionTool<T extends string, U extends z.AnyZodObject | undefined, K extends ChatCompletionToolCall<T, U, any>> { | ||
name: T; | ||
description: string; | ||
params: U; | ||
call: K; | ||
constructor(config: ChatCompletionToolConfig<T, U, K>); | ||
} | ||
interface CreateChatCompletionParams<TStream extends boolean | undefined, TChatCompletionTool extends AnyChatCompletionTool[] | undefined> { | ||
prompt?: string; | ||
model?: string; | ||
systemRole?: string; | ||
stream?: TStream; | ||
messages?: ChatCompletionMessage[]; | ||
tools?: TChatCompletionTool; | ||
toolCallHandlers?: TChatCompletionTool extends AnyChatCompletionTool[] ? { | ||
[K in TChatCompletionTool[number] as K["name"]]?: (tool: K, params: K["params"] extends z$1.AnyZodObject ? z$1.infer<K["params"]> : undefined) => Promise<void>; | ||
} : undefined; | ||
toolCallResultHandlers?: TChatCompletionTool extends AnyChatCompletionTool[] ? { | ||
[K in TChatCompletionTool[number] as K["name"]]?: (tool: K, result: Awaited<ReturnType<K["call"]>>, params: K["params"] extends z$1.AnyZodObject ? z$1.infer<K["params"]> : undefined) => Promise<void>; | ||
} : undefined; | ||
} | ||
type CreateChatCompletionResult<TStream extends boolean | undefined> = TStream extends true ? ChatCompletionStream : ChatCompletion; | ||
declare abstract class ChatCompletionsManager<TChatCompletionTool extends AnyChatCompletionTool[] | undefined> { | ||
tools: TChatCompletionTool; | ||
initTools(tools: TChatCompletionTool): void; | ||
abstract getModels(): Promise<string[]> | string[]; | ||
handleStream(stream: ChatCompletionStream, onChunk?: OnChatCompletionChunk): Promise<ChatCompletion>; | ||
abstract create(params: CreateChatCompletionParams<any, any>): Promise<CreateChatCompletionResult<any>>; | ||
} | ||
type OpenAIChatCompletionModel = ChatCompletionCreateParamsBase["model"]; | ||
interface _OpenAICreateChatCompletionParams extends Omit<Partial<ChatCompletionCreateParamsBase>, keyof CreateChatCompletionParams<any, any>> { | ||
} | ||
interface OpenAICreateChatCompletionParams<TStream extends boolean | undefined, TChatCompletionTool extends AnyChatCompletionTool[] | undefined> extends CreateChatCompletionParams<TStream, TChatCompletionTool>, _OpenAICreateChatCompletionParams { | ||
model?: OpenAIChatCompletionModel; | ||
} | ||
declare class OpenAIChatCompletions<TChatCompletionTool extends AnyChatCompletionTool[] | undefined> extends ChatCompletionsManager<TChatCompletionTool> { | ||
private _openai; | ||
constructor(_openai: OpenAI); | ||
getModels(): OpenAIChatCompletionModel[]; | ||
create<TStream extends boolean | undefined = false, TChatCompletionTool extends AnyChatCompletionTool[] | undefined = undefined>({ prompt, systemRole, messages, tools, toolCallHandlers, toolCallResultHandlers, ...params }: OpenAICreateChatCompletionParams<TStream, MergeChatCompletionTools<TChatCompletionTool, TChatCompletionTool>>): Promise<CreateChatCompletionResult<TStream>>; | ||
} | ||
type Embedding = number[]; | ||
interface CreateEmbeddingsParams { | ||
model?: string; | ||
} | ||
declare abstract class EmbeddingsManager { | ||
abstract getModels(): string[]; | ||
abstract create(input: string | string[], params?: CreateEmbeddingsParams): Promise<Embedding[]>; | ||
} | ||
type _OpenAICreateEmbeddingsParams = Omit<Partial<EmbeddingCreateParams>, "input" | keyof CreateEmbeddingsParams>; | ||
type OpenAIEmbeddingModel = EmbeddingCreateParams["model"]; | ||
interface OpenAICreateEmbeddingsParams extends CreateEmbeddingsParams, _OpenAICreateEmbeddingsParams { | ||
model?: OpenAIEmbeddingModel; | ||
} | ||
declare class OpenAIEmbeddingsManager extends EmbeddingsManager { | ||
private _openai; | ||
constructor(_openai: OpenAI); | ||
getModels(): OpenAIEmbeddingModel[]; | ||
create(input: string | string[], params?: OpenAICreateEmbeddingsParams): Promise<Embedding[]>; | ||
} | ||
declare function parseLengthErrorMessage(message: Error["message"]): [length: number | undefined, maxLength: number | undefined]; | ||
declare class MessageLengthExceededError extends Error { | ||
message: string; | ||
length?: number; | ||
maxLength?: number; | ||
cause?: unknown; | ||
constructor(message: string, options?: { | ||
length?: number; | ||
maxLength?: number; | ||
cause?: unknown; | ||
}); | ||
} | ||
declare class MessagesLengthExceededError extends Error { | ||
message: string; | ||
length?: number; | ||
maxLength?: number; | ||
cause?: unknown; | ||
constructor(message: string, options?: { | ||
length?: number; | ||
maxLength?: number; | ||
cause?: unknown; | ||
}); | ||
} | ||
interface AIConfig<TChatCompletionTools extends AnyChatCompletionTool[] | undefined, TChatCompletionsManager extends ChatCompletionsManager<TChatCompletionTools>, TEmbeddingsManager extends EmbeddingsManager> { | ||
@@ -135,2 +22,2 @@ openAIApiKey?: string; | ||
export { AI, type AIConfig, type AnyAI, type AnyChatCompletionTool, type ChatCompletion, type ChatCompletionMessage, type ChatCompletionStream, ChatCompletionTool, type ChatCompletionToolCall, ChatCompletionsManager, type CreateChatCompletionParams, type CreateChatCompletionResult, type CreateEmbeddingsParams, type Embedding, EmbeddingsManager, type MergeChatCompletionTools, MessageLengthExceededError, MessagesLengthExceededError, type OnChatCompletionChunk, type OpenAIChatCompletionModel, OpenAIChatCompletions, type OpenAICreateChatCompletionParams, type OpenAICreateEmbeddingsParams, type OpenAIEmbeddingModel, OpenAIEmbeddingsManager, parseLengthErrorMessage }; | ||
export { AI, type AIConfig, type AnyAI }; |
@@ -33,13 +33,9 @@ "use strict"; | ||
__export(src_exports, { | ||
AI: () => AI, | ||
ChatCompletionTool: () => ChatCompletionTool, | ||
ChatCompletionsManager: () => ChatCompletionsManager, | ||
EmbeddingsManager: () => EmbeddingsManager, | ||
MessageLengthExceededError: () => MessageLengthExceededError, | ||
MessagesLengthExceededError: () => MessagesLengthExceededError, | ||
parseLengthErrorMessage: () => parseLengthErrorMessage | ||
AI: () => AI | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
var import_openai2 = require("openai"); | ||
// src/ai.ts | ||
var import_openai2 = __toESM(require("openai")); | ||
// src/chat-completions/manager.ts | ||
@@ -266,16 +262,2 @@ var ChatCompletionsManager = class { | ||
// src/chat-completions/tool.ts | ||
var ChatCompletionTool = class { | ||
name; | ||
description; | ||
params; | ||
call; | ||
constructor(config) { | ||
this.name = config.name; | ||
this.description = config.description; | ||
this.params = config.params; | ||
this.call = config.call; | ||
} | ||
}; | ||
// src/embeddings/manager.ts | ||
@@ -301,3 +283,3 @@ var EmbeddingsManager = class { | ||
// src/index.ts | ||
// src/ai.ts | ||
var AI = class { | ||
@@ -307,3 +289,3 @@ embeddings; | ||
constructor(config) { | ||
const openai = new import_openai2.OpenAI({ apiKey: config.openAIApiKey }); | ||
const openai = new import_openai2.default({ apiKey: config.openAIApiKey }); | ||
this.chatCompletions = config.chatCompletionsManager ?? new OpenAIChatCompletions(openai); | ||
@@ -318,10 +300,4 @@ this.embeddings = config.embeddingsManager ?? new OpenAIEmbeddingsManager(openai); | ||
0 && (module.exports = { | ||
AI, | ||
ChatCompletionTool, | ||
ChatCompletionsManager, | ||
EmbeddingsManager, | ||
MessageLengthExceededError, | ||
MessagesLengthExceededError, | ||
parseLengthErrorMessage | ||
AI | ||
}); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@singlestore/ai", | ||
"version": "0.0.27", | ||
"version": "0.0.28", | ||
"license": "Apache-2.0", | ||
@@ -18,2 +18,17 @@ "sideEffects": false, | ||
"require": "./dist/index.js" | ||
}, | ||
"./chat-completions": { | ||
"types": "./dist/chat-completions/index.d.ts", | ||
"import": "./dist/chat-completions/index.mjs", | ||
"require": "./dist/chat-completions/index.js" | ||
}, | ||
"./chat-completions/errors": { | ||
"types": "./dist/chat-completions/errors.d.ts", | ||
"import": "./dist/chat-completions/errors.mjs", | ||
"require": "./dist/chat-completions/errors.js" | ||
}, | ||
"./embeddings": { | ||
"types": "./dist/embeddings.d.ts", | ||
"import": "./dist/embeddings.mjs", | ||
"require": "./dist/embeddings.js" | ||
} | ||
@@ -20,0 +35,0 @@ }, |
268
README.md
@@ -1,21 +0,37 @@ | ||
# SingleStoreAI | ||
# SingleStore AI | ||
A module that enhances the `@singlestore/client` package with AI functionality, allowing you to integrate advanced AI features like embeddings and chat completions. | ||
A module that enhances the [`@singlestore/client`](https://github.com/singlestore-labs/singlestore/tree/main/packages/client) package with AI functionality, allowing you to integrate AI features like embeddings and chat completions. | ||
<details> | ||
<summary> | ||
## Table of Contents | ||
</summary> | ||
- [Installation](#installation) | ||
- [Usage Examples](#usage-examples) | ||
- [Create an Instance](#create-an-instance) | ||
- [Generate Embeddings](#generate-embeddings) | ||
- [Create a Chat Completion](#create-a-chat-completion) | ||
- [Stream Chat Completions](#stream-chat-completions) | ||
- [Develop a Chat Completion Tool](#develop-a-chat-completion-tool) | ||
- [Custom Chat Completions](#custom-chat-completions) | ||
- [Custom Embeddings](#custom-embeddings) | ||
- [Usage](#usage) | ||
- [Initialization](#initialization) | ||
- [Default](#default) | ||
- [With Custom Embeddings Manager](#with-custom-embeddings-manager) | ||
- [With Custom Chat Completions Manager](#with-custom-chat-completions-manager) | ||
- [With Custom Chat Completion Tools](#with-custom-chat-completion-tools) | ||
- [Additional Notes](#additional-notes) | ||
- [Embeddings](#embeddings) | ||
- [Get Embedding Models](#get-embedding-models) | ||
- [Create Embeddings](#create-embeddings) | ||
- [Create Single Embedding](#create-single-embedding) | ||
- [Create Multiple Embeddings](#create-multiple-embeddings) | ||
- [Additional Notes](#additional-notes) | ||
- [Chat Completions](#chat-completions) | ||
- [Get Chat Completion Models](#get-chat-completion-models) | ||
- [Create Chat Completion](#create-chat-completion) | ||
- [As String](#as-string) | ||
- [As Stream](#as-stream) | ||
- [Additional Notes](#additional-notes-1) | ||
</details> | ||
## Installation | ||
To install the `@singlestore/ai` package, run the following command: | ||
```bash | ||
@@ -25,75 +41,97 @@ npm install @singlestore/ai | ||
## Usage Examples | ||
## Usage | ||
### Create an Instance | ||
### Initialization | ||
First, create an instance of the `SingleStoreAI` class using your OpenAI API key. | ||
The `AI` class can be initialized in various ways depending on your requirements. You can start with the default setup, or extend it with custom managers for embeddings and chat completions, or even add custom tools. | ||
#### Default | ||
This is the simplest way to initialize the `AI` class, using an OpenAI API key. | ||
```ts | ||
import { AI } from "@singlestore/ai"; | ||
const ai = new SingleStoreAI({ openAIApiKey: "<OPENAI_API_KEY>" }); | ||
const ai = new AI({ openAIApiKey: "<OPENAI_API_KEY>" }); | ||
``` | ||
### Generate Embeddings | ||
#### With Custom Embeddings Manager | ||
Generate embeddings for a given input text using the `create` method. | ||
You can define a custom embeddings manager by extending the `EmbeddingsManager` class to handle how embeddings are created and models are selected. | ||
```ts | ||
const input = "Hi!"; | ||
const embeddings = await ai.embeddings.create(input); | ||
console.log(embeddings); | ||
``` | ||
import { type CreateEmbeddingsParams, type Embedding, EmbeddingsManager } from "@singlestore/ai/embeddings"; | ||
### Create a Chat Completion | ||
class CustomEmbeddingsManager extends EmbeddingsManager { | ||
getModels(): string[] { | ||
return ["<MODEL_NAME>"]; | ||
} | ||
Create a chat completion. | ||
async create(input: string | string[], params?: CreateEmbeddingsParams): Promise<Embedding[]> { | ||
const embeddings: Embedding[] = await customFnCall(); | ||
return embeddings; | ||
} | ||
} | ||
```ts | ||
const prompt = "Hi, how are you?"; | ||
const chatCompletion = await ai.chatCompletions.create({ | ||
prompt, | ||
model: "gpt-4o", | ||
systemRole: "You are a helpful assistant", | ||
const ai = new AI({ | ||
openAIApiKey: "<OPENAI_API_KEY>", | ||
embeddingsManager: new CustomEmbeddingsManager(), | ||
}); | ||
console.log(chatCompletion); | ||
``` | ||
### Stream Chat Completions | ||
#### With Custom Chat Completions Manager | ||
Stream chat completions to handle responses in real time. | ||
You can define a custom chat completions manager by extending the `ChatCompletionsManager` class. This allows you to modify how chat completions are handled, whether in a streaming or non-streaming fashion. | ||
```ts | ||
const prompt = "Hi, how are you?"; | ||
import { | ||
type AnyChatCompletionTool, | ||
ChatCompletionsManager, | ||
type CreateChatCompletionParams, | ||
type CreateChatCompletionResult, | ||
type MergeChatCompletionTools, | ||
} from "@singlestore/ai/chat-completions"; | ||
const stream = await ai.chatCompletions.create({ | ||
prompt, | ||
model: "gpt-4o", | ||
systemRole: "You are a helpful assistant", | ||
stream: true, | ||
}); | ||
type ChatCompletionTools = undefined; // If an array of custom tools is created, use `typeof tools`. | ||
const onChunk: OnChatCompletionChunk = (chunk) => { | ||
console.log("onChunk:", chunk); | ||
}; | ||
class CustomChatCompletionsManager extends ChatCompletionsManager<ChatCompletionTools> { | ||
getModels(): Promise<string[]> | string[] { | ||
return ["<MODEL_NAME>"]; | ||
} | ||
const chatCompletion = await ai.chatCompletions.handleStream(stream, onChunk); | ||
console.log(chatCompletion); | ||
create<TStream extends boolean, TTools extends AnyChatCompletionTool[] | undefined>( | ||
params: CreateChatCompletionParams<TStream, MergeChatCompletionTools<ChatCompletionTools, TTools>>, | ||
): Promise<CreateChatCompletionResult<TStream>> { | ||
if (params.stream) { | ||
const stream = customFnCall(); | ||
return stream as Promise<CreateChatCompletionResult<TStream>>; | ||
} | ||
const chatCompletion = await customFnCall(); | ||
return chatCompletion as Promise<CreateChatCompletionResult<TStream>>; | ||
} | ||
} | ||
const ai = new AI({ | ||
openAIApiKey: "<OPENAI_API_KEY>", | ||
chatCompletionsManager: new CustomChatCompletionsManager(), | ||
}); | ||
``` | ||
### Develop a Chat Completion Tool | ||
#### With Custom Chat Completion Tools | ||
Create a custom chat completion tool to handle specific tasks. | ||
You can also create custom tools to extend the functionality of the chat completions by defining them with the `ChatCompletionTool` class. | ||
```ts | ||
import { AI, ChatCompletionTool } from "@singlestore/ai"; | ||
import { ChatCompletionTool } from "@singlestore/ai/chat-completions"; | ||
import { z } from "zod"; | ||
const findCityInfoTool = new ChatCompletionTool({ | ||
name: "find_city_info", | ||
description: "Useful for finding and displaying information about a city.", | ||
params: z.object({ name: z.string().describe("The city name") }), | ||
const customTool = new ChatCompletionTool({ | ||
name: "<TOOL_NAME>", | ||
description: "<TOOL_DESCRIPTION>", | ||
params: z.object({ paramName: z.string().describe("<PARAM_DESCRIPTION>") }), | ||
call: async (params) => { | ||
const info = `${params.name} is known as a great city!`; | ||
return { name: "find_city_info", params, value: JSON.stringify(info) }; | ||
const value = await anyFnCall(params); | ||
return { name: "<TOOL_NAME>", params, value: JSON.stringify(value) }; | ||
}, | ||
@@ -103,70 +141,98 @@ }); | ||
const ai = new AI({ | ||
openAIApiKey: "<OPENAI_API_KEY>", | ||
chatCompletionTools: [findCityInfoTool], | ||
tools: [customTool], | ||
... | ||
}); | ||
const chatCompletion = await ai.chatCompletions.create({ prompt: "Find info about Vancouver." }); | ||
console.log(chatCompletion); | ||
``` | ||
### Custom Chat Completions | ||
#### Additional Notes | ||
Extend the ChatCompletions class to use a custom LLM for creating chat completions. | ||
- If you declare a custom embeddings manager and a custom chat completions manager, the `openAIApiKey` parameter is not required. | ||
- Custom managers and tools allow for extensive customization, giving you the flexibility to integrate AI functionality tailored to your specific needs. | ||
--- | ||
### Embeddings | ||
#### Get Embedding Models | ||
```ts | ||
import { AI, type AnyChatCompletionTool, ChatCompletions } from "@singlestore/ai"; | ||
const models = ai.embeddings.getModels(); | ||
``` | ||
class CustomChatCompletionsManager< | ||
TChatCompletionTool extends AnyChatCompletionTool[] | undefined, | ||
> extends ChatCompletions<TChatCompletionTool> { | ||
constructor() { | ||
super(); | ||
} | ||
--- | ||
getModels(): Promise<string[]> | string[] { | ||
// Your implementation | ||
return []; | ||
} | ||
#### Create Embeddings | ||
async create<TStream extends boolean | undefined>( | ||
params: CreateChatCompletionParams<TStream, TChatCompletionTool>, | ||
): Promise<CreateChatCompletionResult<TStream>> { | ||
// Your implementation | ||
return {} as CreateChatCompletionResult<TStream>; | ||
} | ||
} | ||
##### Create Single Embedding | ||
const ai = new AI({ | ||
openAIApiKey: "<OPENAI_API_KEY>", | ||
chatCompletions: new CustomChatCompletionsManager(), | ||
```ts | ||
const embeddings = await ai.embeddings.create("<INPUT>", { | ||
model: "<MODEL_NAME>", // Optional | ||
dimensions: "<DIMENSION>", // Optional | ||
}); | ||
``` | ||
### Custom Embeddings | ||
##### Create Multiple Embeddings | ||
Create a custom embeddings class to use a custom LLM for creating embeddings. | ||
```ts | ||
const embeddings = await ai.embeddings.create(["<INPUT>", "<INPUT_2>"], ...); | ||
``` | ||
##### Additional Notes | ||
- If a custom `EmbeddingsManager` is provided, all the parameters can still be passed to the `ai.embeddings.create` method, allowing for custom handling and logic while preserving the same interface. | ||
--- | ||
### Chat Completions | ||
#### Get Chat Completion Models | ||
```ts | ||
import { AI, Embeddings } from "@singlestore/ai"; | ||
const models = ai.chatCompletions.getModels(); | ||
``` | ||
class CustomEmbeddingsManager extends Embeddings { | ||
constructor() { | ||
super(); | ||
} | ||
#### Create Chat Completion | ||
getModels(): string[] { | ||
// Your implementation | ||
return []; | ||
} | ||
The `create` method allows you to generate chat completions either as a complete string or in a streamed fashion, depending on the `stream` option. | ||
async create(input: string | string[], params?: CreateEmbeddingsParams): Promise<Embedding[]> { | ||
// Your implementation | ||
return []; | ||
} | ||
} | ||
##### As String | ||
const ai = new AI({ | ||
openAIApiKey: "<OPENAI_API_KEY>", | ||
embeddings: new CustomEmbeddingsManager(), | ||
Performs a chat completion and returns the result as a complete string. | ||
```ts | ||
const chatCompletion = await ai.chatCompletions.create({ | ||
stream: false, | ||
prompt: "<PROMPT>", | ||
model: "<MODEL_NAME>", // Optional | ||
systemRole: "<SYSTEM_ROLE>", // Optional | ||
messages: [{ role: "user", content: "<CONTENT>" }], // Optional | ||
}); | ||
``` | ||
##### As Stream | ||
Performs a chat completion and returns the result as a stream of data chunks. | ||
```ts | ||
const stream = await ai.chatCompletions.create({ | ||
stream: true, | ||
prompt: "<PROMPT>", | ||
model: "<MODEL_NAME>", // Optional | ||
systemRole: "<SYSTEM_ROLE>", // Optional | ||
messages: [{ role: "user", content: "<CONTENT>" }], // Optional | ||
tools: [...] // Optional | ||
}); | ||
const chatCompletion = await ai.chatCompletions.handleStream(stream, async (chunk) => { | ||
await customFnCall(chunk); | ||
}); | ||
``` | ||
##### Additional Notes | ||
- When using `stream: true`, the `handleStream` function processes the stream and accepts a callback function as the second argument. The callback handles each new chunk of data as it arrives. | ||
- You can use the messages array to provide additional context for the chat completion, such as user messages or system instructions. | ||
- If a custom `ChatCompletionsManager` is provided, all the parameters can still be passed to the `ai.chatCompletions.create` method, allowing for custom handling and logic while preserving the same interface. | ||
--- |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
128889
32
1120
237
1