feat: enhance AI Core with new client and plugin system features

- Introduced `PluginEnabledAiClient` for a more flexible client interface with integrated plugin support.
- Updated `ApiClientFactory` and `UniversalAiSdkClient` to utilize new provider settings for improved type safety.
- Added a comprehensive plugin management system, allowing for dynamic plugin registration and execution.
- Enhanced the provider registry to include new AI providers and updated existing provider settings.
- Removed deprecated files and streamlined the codebase for better maintainability and clarity.
- Updated documentation to reflect new features and usage examples for the plugin system.
This commit is contained in:
MyPrototypeWhat 2025-06-18 19:23:14 +08:00
parent 8910281b09
commit c51bcdefc5
17 changed files with 1494 additions and 253 deletions

View File

@ -15,6 +15,7 @@ Cherry Studio AI Core 是一个基于 Vercel AI SDK 的统一 AI Provider 接口
基于 [AI SDK 官方支持的 providers](https://ai-sdk.dev/providers/ai-sdk-providers)
**核心 Providers:**
- OpenAI
- Anthropic
- Google Generative AI
@ -25,6 +26,7 @@ Cherry Studio AI Core 是一个基于 Vercel AI SDK 的统一 AI Provider 接口
- Amazon Bedrock
**扩展 Providers:**
- Cohere
- Groq
- Together.ai
@ -64,17 +66,13 @@ const client = await createAiSdkClient('openai', {
// 流式生成
const result = await client.stream({
modelId: 'gpt-4',
messages: [
{ role: 'user', content: 'Hello!' }
]
messages: [{ role: 'user', content: 'Hello!' }]
})
// 非流式生成
const response = await client.generate({
modelId: 'gpt-4',
messages: [
{ role: 'user', content: 'Hello!' }
]
messages: [{ role: 'user', content: 'Hello!' }]
})
```
@ -89,12 +87,9 @@ const client = await createOpenAIClient({
})
// 便捷流式生成
const result = await streamGeneration(
'openai',
'gpt-4',
[{ role: 'user', content: 'Hello!' }],
{ apiKey: 'your-api-key' }
)
const result = await streamGeneration('openai', 'gpt-4', [{ role: 'user', content: 'Hello!' }], {
apiKey: 'your-api-key'
})
```
### 多 Provider 支持
@ -111,4 +106,4 @@ const xaiClient = await createAiSdkClient('xai', { apiKey: 'xai-key' })
## License
MIT
MIT

View File

@ -41,12 +41,12 @@
"@ai-sdk/togetherai": "^0.2.14",
"@ai-sdk/vercel": "^0.0.1",
"@ai-sdk/xai": "^1.2.16",
"@openrouter/ai-sdk-provider": "^0.1.0",
"ai": "^4.3.16",
"anthropic-vertex-ai": "^1.0.2",
"ollama-ai-provider": "^1.2.0",
"qwen-ai-provider": "^0.1.0",
"zhipu-ai-provider": "^0.1.1",
"@openrouter/ai-sdk-provider": "^0.1.0"
"zhipu-ai-provider": "^0.1.1"
},
"peerDependenciesMeta": {
"@ai-sdk/amazon-bedrock": {
@ -120,6 +120,5 @@
"import": "./dist/index.js",
"require": "./dist/index.js"
}
},
"packageManager": "pnpm"
}
}

View File

@ -6,7 +6,7 @@
import type { LanguageModelV1 } from 'ai'
import { aiProviderRegistry } from '../providers/registry'
import { ProviderOptions } from './types'
import { type ProviderId, type ProviderSettingsMap } from './types'
// 客户端配置接口
export interface ClientConfig {
@ -33,23 +33,29 @@ export class ClientFactoryError extends Error {
export class ApiClientFactory {
/**
* AI SDK
* LanguageModelV1 streamText/generateText
* Provider 使 Provider 使 openai-compatible
*/
static async createClient<T extends ProviderId>(
providerId: T,
modelId: string,
options: ProviderSettingsMap[T]
): Promise<LanguageModelV1>
static async createClient(
providerId: string,
modelId: string = 'default',
options: ProviderOptions
): Promise<LanguageModelV1> {
modelId: string,
options: ProviderSettingsMap['openai-compatible']
): Promise<LanguageModelV1>
static async createClient(providerId: string, modelId: string = 'default', options: any): Promise<LanguageModelV1> {
try {
// 验证provider是否支持
if (!aiProviderRegistry.isSupported(providerId)) {
throw new ClientFactoryError(`Provider "${providerId}" is not supported`, providerId)
}
// 对于不在注册表中的 provider默认使用 openai-compatible
const effectiveProviderId = aiProviderRegistry.isSupported(providerId) ? providerId : 'openai-compatible'
// 获取Provider配置
const providerConfig = aiProviderRegistry.getProvider(providerId)
const providerConfig = aiProviderRegistry.getProvider(effectiveProviderId)
if (!providerConfig) {
throw new ClientFactoryError(`Provider "${providerId}" is not registered`, providerId)
throw new ClientFactoryError(`Provider "${effectiveProviderId}" is not registered`, providerId)
}
// 动态导入模块
@ -60,10 +66,9 @@ export class ApiClientFactory {
if (typeof creatorFunction !== 'function') {
throw new ClientFactoryError(
`Creator function "${providerConfig.creatorFunctionName}" not found in the imported module for provider "${providerId}"`
`Creator function "${providerConfig.creatorFunctionName}" not found in the imported module for provider "${effectiveProviderId}"`
)
}
// 创建provider实例
const provider = creatorFunction(options)
@ -71,7 +76,7 @@ export class ApiClientFactory {
if (typeof provider === 'function') {
return provider(modelId)
} else {
throw new ClientFactoryError(`Unknown model access pattern for provider "${providerId}"`)
throw new ClientFactoryError(`Unknown model access pattern for provider "${effectiveProviderId}"`)
}
} catch (error) {
if (error instanceof ClientFactoryError) {
@ -105,19 +110,36 @@ export class ApiClientFactory {
id: string
name: string
isSupported: boolean
effectiveProvider: string
} {
const provider = aiProviderRegistry.getProvider(providerId)
const effectiveProviderId = aiProviderRegistry.isSupported(providerId) ? providerId : 'openai-compatible'
const provider = aiProviderRegistry.getProvider(effectiveProviderId)
return {
id: providerId,
name: provider?.name || providerId,
isSupported: aiProviderRegistry.isSupported(providerId)
isSupported: aiProviderRegistry.isSupported(providerId),
effectiveProvider: effectiveProviderId
}
}
}
// 便捷导出函数
export const createClient = (providerId: string, modelId?: string, options?: any) =>
ApiClientFactory.createClient(providerId, modelId, options)
export function createClient<T extends ProviderId>(
providerId: T,
modelId: string,
options: ProviderSettingsMap[T]
): Promise<LanguageModelV1>
export function createClient(
providerId: string,
modelId: string,
options: ProviderSettingsMap['openai-compatible']
): Promise<LanguageModelV1>
export function createClient(providerId: string, modelId: string = 'default', options: any): Promise<LanguageModelV1> {
return ApiClientFactory.createClient(providerId, modelId, options)
}
export const getSupportedProviders = () => ApiClientFactory.getSupportedProviders()

View File

@ -0,0 +1,306 @@
/**
* AI Client - Cherry Studio AI Core
* AI
*
* ## 使
*
* ```typescript
* import { AiClient } from '@cherry-studio/ai-core'
*
* // 创建客户端(默认带插件系统)
* const client = AiClient.create('openai', {
* name: 'openai',
* apiKey: process.env.OPENAI_API_KEY
* }, [LoggingPlugin, ContentFilterPlugin])
*
* // 使用方式与 UniversalAiSdkClient 完全相同
* const result = await client.generateText('gpt-4', {
* messages: [{ role: 'user', content: 'Hello!' }]
* })
* ```
*/
import { generateObject, generateText, streamObject, streamText } from 'ai'
import { AiPlugin, createContext, PluginManager } from '../plugins'
import { ApiClientFactory } from './ApiClientFactory'
import { type ProviderId, type ProviderSettingsMap } from './types'
import { UniversalAiSdkClient } from './UniversalAiSdkClient'
/**
* Cherry Studio AI Core
* AI
*/
export class PluginEnabledAiClient<T extends ProviderId = ProviderId> {
private pluginManager: PluginManager
private baseClient: UniversalAiSdkClient<T>
constructor(
private readonly providerId: T,
private readonly options: ProviderSettingsMap[T],
plugins: AiPlugin[] = []
) {
this.pluginManager = new PluginManager(plugins)
this.baseClient = UniversalAiSdkClient.create(providerId, options)
}
/**
*
*/
use(plugin: AiPlugin): this {
this.pluginManager.use(plugin)
return this
}
/**
*
*/
usePlugins(plugins: AiPlugin[]): this {
plugins.forEach((plugin) => this.pluginManager.use(plugin))
return this
}
/**
*
*/
removePlugin(pluginName: string): this {
this.pluginManager.remove(pluginName)
return this
}
/**
*
*/
getPluginStats() {
return this.pluginManager.getStats()
}
/**
*
*/
getPlugins() {
return this.pluginManager.getPlugins()
}
/**
*
* 1-5
*/
private async executeWithPlugins<TParams, TResult>(
methodName: string,
modelId: string,
params: TParams,
executor: (finalModelId: string, transformedParams: TParams) => Promise<TResult>
): Promise<TResult> {
// 创建请求上下文
const context = createContext(this.providerId, modelId, params)
try {
// 1. 触发请求开始事件
await this.pluginManager.executeParallel('onRequestStart', context)
// 2. 解析模型别名
const resolvedModelId = await this.pluginManager.executeFirst<string>('resolveModel', modelId, context)
const finalModelId = resolvedModelId || modelId
// 3. 转换请求参数
const transformedParams = await this.pluginManager.executeSequential('transformParams', params, context)
// 4. 执行具体的 API 调用
const result = await executor(finalModelId, transformedParams)
// 5. 转换结果(对于非流式调用)
const transformedResult = await this.pluginManager.executeSequential('transformResult', result, context)
// 6. 触发完成事件
await this.pluginManager.executeParallel('onRequestEnd', context, transformedResult)
return transformedResult
} catch (error) {
// 7. 触发错误事件
await this.pluginManager.executeParallel('onError', context, undefined, error as Error)
throw error
}
}
/**
*
*
*/
private async executeStreamWithPlugins<TParams, TResult>(
methodName: string,
modelId: string,
params: TParams,
executor: (finalModelId: string, transformedParams: TParams, streamTransforms: any[]) => Promise<TResult>
): Promise<TResult> {
// 创建请求上下文
const context = createContext(this.providerId, modelId, params)
try {
// 1. 触发请求开始事件
await this.pluginManager.executeParallel('onRequestStart', context)
// 2. 解析模型别名
const resolvedModelId = await this.pluginManager.executeFirst<string>('resolveModel', modelId, context)
const finalModelId = resolvedModelId || modelId
// 3. 转换请求参数
const transformedParams = await this.pluginManager.executeSequential('transformParams', params, context)
// 4. 收集流转换器
const streamTransforms = this.pluginManager.collectStreamTransforms()
// 5. 执行流式 API 调用
const result = await executor(finalModelId, transformedParams, streamTransforms)
// 6. 触发完成事件(注意:对于流式调用,这里触发的是开始流式响应的事件)
await this.pluginManager.executeParallel('onRequestEnd', context, { stream: true })
return result
} catch (error) {
// 7. 触发错误事件
await this.pluginManager.executeParallel('onError', context, undefined, error as Error)
throw error
}
}
/**
* -
*/
async streamText(
modelId: string,
params: Omit<Parameters<typeof streamText>[0], 'model'>
): Promise<ReturnType<typeof streamText>> {
return this.executeStreamWithPlugins(
'streamText',
modelId,
params,
async (finalModelId, transformedParams, streamTransforms) => {
// 对于流式调用,需要直接调用 AI SDK 以支持流转换器
const model = await ApiClientFactory.createClient(this.providerId, finalModelId, this.options)
return streamText({
model,
...transformedParams,
experimental_transform: streamTransforms.length > 0 ? streamTransforms : undefined
})
}
)
}
/**
* -
*/
async generateText(
modelId: string,
params: Omit<Parameters<typeof generateText>[0], 'model'>
): Promise<ReturnType<typeof generateText>> {
return this.executeWithPlugins('generateText', modelId, params, async (finalModelId, transformedParams) => {
return this.baseClient.generateText(finalModelId, transformedParams)
})
}
/**
* -
*/
async generateObject(
modelId: string,
params: Omit<Parameters<typeof generateObject>[0], 'model'>
): Promise<ReturnType<typeof generateObject>> {
return this.executeWithPlugins('generateObject', modelId, params, async (finalModelId, transformedParams) => {
return this.baseClient.generateObject(finalModelId, transformedParams)
})
}
/**
* -
* streamObject 使
*/
async streamObject(
modelId: string,
params: Omit<Parameters<typeof streamObject>[0], 'model'>
): Promise<ReturnType<typeof streamObject>> {
return this.executeWithPlugins('streamObject', modelId, params, async (finalModelId, transformedParams) => {
return this.baseClient.streamObject(finalModelId, transformedParams)
})
}
/**
*
*/
getClientInfo() {
return this.baseClient.getClientInfo()
}
/**
*
*/
getBaseClient(): UniversalAiSdkClient<T> {
return this.baseClient
}
// === 静态工厂方法 ===
/**
* OpenAI Compatible
*/
static createOpenAICompatible(
config: ProviderSettingsMap['openai-compatible'],
plugins: AiPlugin[] = []
): PluginEnabledAiClient<'openai-compatible'> {
return new PluginEnabledAiClient('openai-compatible', config, plugins)
}
/**
*
*/
static create<T extends ProviderId>(
providerId: T,
options: ProviderSettingsMap[T],
plugins?: AiPlugin[]
): PluginEnabledAiClient<T>
static create(
providerId: string,
options: ProviderSettingsMap['openai-compatible'],
plugins?: AiPlugin[]
): PluginEnabledAiClient<'openai-compatible'>
static create(providerId: string, options: any, plugins: AiPlugin[] = []): PluginEnabledAiClient {
if (providerId in ({} as ProviderSettingsMap)) {
return new PluginEnabledAiClient(providerId as ProviderId, options, plugins)
} else {
// 对于未知 provider使用 openai-compatible
return new PluginEnabledAiClient('openai-compatible', options, plugins)
}
}
}
/**
* AI
*/
export function createClient<T extends ProviderId>(
providerId: T,
options: ProviderSettingsMap[T],
plugins?: AiPlugin[]
): PluginEnabledAiClient<T>
export function createClient(
providerId: string,
options: ProviderSettingsMap['openai-compatible'],
plugins?: AiPlugin[]
): PluginEnabledAiClient<'openai-compatible'>
export function createClient(providerId: string, options: any, plugins: AiPlugin[] = []): PluginEnabledAiClient {
return PluginEnabledAiClient.create(providerId, options, plugins)
}
/**
* OpenAI Compatible 便
*/
export function createCompatibleClient(
config: ProviderSettingsMap['openai-compatible'],
plugins: AiPlugin[] = []
): PluginEnabledAiClient<'openai-compatible'> {
return PluginEnabledAiClient.createOpenAICompatible(config, plugins)
}

View File

@ -1,21 +1,93 @@
/**
* Universal AI SDK Client
* AI SDK客户端实现
*
* ## 使
*
* ### 1.
* ```typescript
* import { UniversalAiSdkClient } from '@cherry-studio/ai-core'
*
* // OpenAI
* const openai = UniversalAiSdkClient.create('openai', {
* name: 'openai',
* apiHost: 'https://api.openai.com/v1',
* apiKey: process.env.OPENAI_API_KEY
* })
*
* // Anthropic
* const anthropic = UniversalAiSdkClient.create('anthropic', {
* name: 'anthropic',
* apiHost: 'https://api.anthropic.com',
* apiKey: process.env.ANTHROPIC_API_KEY
* })
* ```
*
* ### 2. OpenAI Compatible
* ```typescript
* // LM Studio (本地运行)
* const lmStudio = UniversalAiSdkClient.createOpenAICompatible({
* name: 'lm-studio',
* baseURL: 'http://localhost:1234/v1'
* })
*
* // Ollama (本地运行)
* const ollama = UniversalAiSdkClient.createOpenAICompatible({
* name: 'ollama',
* baseURL: 'http://localhost:11434/v1'
* })
*
* // 自定义第三方 API
* const customProvider = UniversalAiSdkClient.createOpenAICompatible({
* name: 'my-provider',
* apiKey: process.env.CUSTOM_API_KEY,
* baseURL: 'https://api.customprovider.com/v1',
* headers: {
* 'X-Custom-Header': 'value',
* 'User-Agent': 'MyApp/1.0'
* },
* queryParams: {
* 'api-version': '2024-01'
* }
* })
* ```
*
* ### 3. 使 AI
* ```typescript
* // 流式文本生成
* const stream = await client.streamText('gpt-4', {
* messages: [{ role: 'user', content: 'Hello!' }]
* })
*
* // 生成文本
* const { text } = await client.generateText('gpt-4', {
* messages: [{ role: 'user', content: 'Hello!' }]
* })
*
* // 生成结构化对象
* const { object } = await client.generateObject('gpt-4', {
* messages: [{ role: 'user', content: 'Generate a user profile' }],
* schema: z.object({
* name: z.string(),
* age: z.number()
* })
* })
* ```
*/
import { generateObject, generateText, streamObject, streamText } from 'ai'
import { ApiClientFactory } from './ApiClientFactory'
import { ProviderOptions } from './types'
import { type ProviderId, type ProviderSettingsMap } from './types'
/**
* AI SDK
* AI
*/
export class UniversalAiSdkClient {
export class UniversalAiSdkClient<T extends ProviderId = ProviderId> {
constructor(
private readonly providerId: string,
private readonly options: ProviderOptions
private readonly providerId: T,
private readonly options: ProviderSettingsMap[T]
) {}
/**
@ -84,11 +156,62 @@ export class UniversalAiSdkClient {
getClientInfo() {
return ApiClientFactory.getClientInfo(this.providerId)
}
// === 静态工厂方法 ===
/**
* OpenAI Compatible
* OpenAI API
*/
static createOpenAICompatible(
config: ProviderSettingsMap['openai-compatible']
): UniversalAiSdkClient<'openai-compatible'> {
return new UniversalAiSdkClient('openai-compatible', config)
}
/**
*
* Provider 使 Provider 使 openai-compatible
*/
static create<T extends ProviderId>(providerId: T, options: ProviderSettingsMap[T]): UniversalAiSdkClient<T>
static create(
providerId: string,
options: ProviderSettingsMap['openai-compatible']
): UniversalAiSdkClient<'openai-compatible'>
static create(providerId: string, options: any): UniversalAiSdkClient {
if (providerId in ({} as ProviderSettingsMap)) {
return new UniversalAiSdkClient(providerId as ProviderId, options)
} else {
// 对于未知 provider使用 openai-compatible
return new UniversalAiSdkClient('openai-compatible', options)
}
}
}
/**
*
*/
export function createUniversalClient(providerId: string, options: any = {}): UniversalAiSdkClient {
return new UniversalAiSdkClient(providerId, options)
export function createUniversalClient<T extends ProviderId>(
providerId: T,
options: ProviderSettingsMap[T]
): UniversalAiSdkClient<T>
export function createUniversalClient(
providerId: string,
options: ProviderSettingsMap['openai-compatible']
): UniversalAiSdkClient<'openai-compatible'>
export function createUniversalClient(providerId: string, options: any): UniversalAiSdkClient {
return UniversalAiSdkClient.create(providerId, options)
}
/**
* OpenAI Compatible 便
*/
export function createOpenAICompatibleClient(
config: ProviderSettingsMap['openai-compatible']
): UniversalAiSdkClient<'openai-compatible'> {
return UniversalAiSdkClient.createOpenAICompatible(config)
}

View File

@ -1,7 +1,66 @@
export type ProviderOptions = {
name: string
import { FetchFunction } from '@ai-sdk/provider-utils'
import type { ProviderSettingsMap } from '../providers/registry'
// ProviderSettings 是所有 Provider Settings 的联合类型
export type ProviderSettings = ProviderSettingsMap[keyof ProviderSettingsMap]
// 基础 Provider 配置类型(为了向后兼容和通用场景)
export type BaseProviderSettings = {
/**
* API key for authentication
*/
apiKey?: string
apiHost: string
apiVersion?: string
headers?: Record<string, string | unknown>
/**
* Base URL for the API calls
*/
baseURL?: string
/**
* Custom headers to include in the requests
*/
headers?: Record<string, string>
/**
* Optional custom url query parameters to include in request urls
*/
queryParams?: Record<string, string>
/**
* Custom fetch implementation. You can use it as a middleware to intercept requests,
* or to provide a custom fetch implementation for e.g. testing.
*/
fetch?: FetchFunction
/**
* Allow additional properties for provider-specific settings
*/
[key: string]: any
}
// 重新导出 ProviderSettingsMap 中的所有类型
export type {
AmazonBedrockProviderSettings,
AnthropicProviderSettings,
AnthropicVertexProviderSettings,
AzureOpenAIProviderSettings,
CerebrasProviderSettings,
CohereProviderSettings,
DeepInfraProviderSettings,
DeepSeekProviderSettings,
FalProviderSettings,
FireworksProviderSettings,
GoogleGenerativeAIProviderSettings,
GoogleVertexProviderSettings,
GroqProviderSettings,
MistralProviderSettings,
OllamaProviderSettings,
OpenAICompatibleProviderSettings,
OpenAIProviderSettings,
OpenRouterProviderSettings,
PerplexityProviderSettings,
ProviderId,
ProviderSettingsMap,
QwenProviderSettings,
ReplicateProviderSettings,
TogetherAIProviderSettings,
VercelProviderSettings,
XaiProviderSettings,
ZhipuProviderSettings
} from '../providers/registry'

View File

@ -5,42 +5,96 @@
// 导入内部使用的类和函数
import { ApiClientFactory } from './clients/ApiClientFactory'
import { createClient } from './clients/PluginEnabledAiClient'
import { type ProviderSettingsMap } from './clients/types'
import { createUniversalClient } from './clients/UniversalAiSdkClient'
import { aiProviderRegistry, isProviderSupported } from './providers/registry'
// 核心导出
// ==================== 主要客户端接口 ====================
// 默认使用集成插件系统的客户端
export {
PluginEnabledAiClient as AiClient,
createClient,
createCompatibleClient
} from './clients/PluginEnabledAiClient'
// 为了向后兼容,也导出原名称
export { PluginEnabledAiClient } from './clients/PluginEnabledAiClient'
// ==================== 插件系统 ====================
export type { AiPlugin, AiRequestContext, HookResult, HookType, PluginManagerConfig } from './plugins'
export { createContext, definePlugin, PluginManager } from './plugins'
// ==================== 底层客户端(高级用法) ====================
// 不带插件系统的基础客户端,用于需要绕过插件系统的场景
export {
createOpenAICompatibleClient as createBasicOpenAICompatibleClient,
createUniversalClient,
UniversalAiSdkClient
} from './clients/UniversalAiSdkClient'
// ==================== 低级 API ====================
export { ApiClientFactory } from './clients/ApiClientFactory'
export { createUniversalClient, UniversalAiSdkClient } from './clients/UniversalAiSdkClient'
export { aiProviderRegistry } from './providers/registry'
// 类型导出
// ==================== 类型定义 ====================
export type { ClientFactoryError } from './clients/ApiClientFactory'
export type { BaseProviderSettings, ProviderSettings } from './clients/types'
export type { ProviderConfig } from './providers/registry'
export type { ProviderError } from './providers/types'
// 便捷函数导出
export { createClient, getClientInfo, getSupportedProviders } from './clients/ApiClientFactory'
// 重新导出所有 Provider Settings 类型
export type {
AmazonBedrockProviderSettings,
AnthropicProviderSettings,
AnthropicVertexProviderSettings,
AzureOpenAIProviderSettings,
CerebrasProviderSettings,
CohereProviderSettings,
DeepInfraProviderSettings,
DeepSeekProviderSettings,
FalProviderSettings,
FireworksProviderSettings,
GoogleGenerativeAIProviderSettings,
GoogleVertexProviderSettings,
GroqProviderSettings,
MistralProviderSettings,
OllamaProviderSettings,
OpenAICompatibleProviderSettings,
OpenAIProviderSettings,
OpenRouterProviderSettings,
PerplexityProviderSettings,
ProviderId,
ProviderSettingsMap,
QwenProviderSettings,
ReplicateProviderSettings,
TogetherAIProviderSettings,
VercelProviderSettings,
XaiProviderSettings,
ZhipuProviderSettings
} from './clients/types'
// ==================== 工具函数 ====================
export { createClient as createApiClient, getClientInfo, getSupportedProviders } from './clients/ApiClientFactory'
export { getAllProviders, getProvider, isProviderSupported, registerProvider } from './providers/registry'
// 默认导出 - 主要的工厂类
export { ApiClientFactory as default } from './clients/ApiClientFactory'
// 包信息
// ==================== 包信息 ====================
export const AI_CORE_VERSION = '1.0.0'
export const AI_CORE_NAME = '@cherry-studio/ai-core'
// 包配置和实用工具
// ==================== 便捷 API ====================
// 主要的便捷工厂类
export const AiCore = {
version: AI_CORE_VERSION,
name: AI_CORE_NAME,
// 快速创建客户端
async createClient(providerId: string, modelId: string = 'default', options: any = {}) {
return ApiClientFactory.createClient(providerId, modelId, options)
// 创建主要客户端(默认带插件系统)
create(providerId: string, options: any = {}, plugins: any[] = []) {
return createClient(providerId, options, plugins)
},
// 创建通用客户端
createUniversalClient(providerId: string, options: any = {}) {
// 创建基础客户端(不带插件系统)
createBasic(providerId: string, options: any = {}) {
return createUniversalClient(providerId, options)
},
@ -60,24 +114,23 @@ export const AiCore = {
}
}
// 便捷的预配置clients创建函数
export const createOpenAIClient = (options: { apiKey: string; baseURL?: string }) => {
return createUniversalClient('openai', options)
export const createOpenAIClient = (options: ProviderSettingsMap['openai'], plugins?: any[]) => {
return createClient('openai', options, plugins)
}
export const createAnthropicClient = (options: { apiKey: string; baseURL?: string }) => {
return createUniversalClient('anthropic', options)
export const createAnthropicClient = (options: ProviderSettingsMap['anthropic'], plugins?: any[]) => {
return createClient('anthropic', options, plugins)
}
export const createGoogleClient = (options: { apiKey: string; baseURL?: string }) => {
return createUniversalClient('google', options)
export const createGoogleClient = (options: ProviderSettingsMap['google'], plugins?: any[]) => {
return createClient('google', options, plugins)
}
export const createXAIClient = (options: { apiKey: string; baseURL?: string }) => {
return createUniversalClient('xai', options)
export const createXAIClient = (options: ProviderSettingsMap['xai'], plugins?: any[]) => {
return createClient('xai', options, plugins)
}
// 调试和开发工具
// ==================== 调试和开发工具 ====================
export const DevTools = {
// 列出所有注册的providers
listProviders() {
@ -90,7 +143,7 @@ export const DevTools = {
// 测试provider连接
async testProvider(providerId: string, options: any) {
try {
const client = createUniversalClient(providerId, options)
const client = createClient(providerId, options)
const info = client.getClientInfo()
return {
success: true,

View File

@ -1,102 +0,0 @@
import { openai } from '@ai-sdk/openai'
import { streamText } from 'ai'
import { createContext, PluginManager } from '..'
import { ContentFilterPlugin, LoggingPlugin } from './example-plugins'
/**
* AI SDK
*/
export async function exampleAiRequest() {
// 1. 创建插件管理器
const pluginManager = new PluginManager([LoggingPlugin, ContentFilterPlugin])
// 2. 创建请求上下文
const context = createContext('openai', 'gpt-4', {
messages: [{ role: 'user', content: 'Hello!' }]
})
try {
// 3. 触发请求开始事件
await pluginManager.executeParallel('onRequestStart', context)
// 4. 解析模型别名
// const resolvedModel = await pluginManager.executeFirst('resolveModel', 'gpt-4', context)
// const modelId = resolvedModel || 'gpt-4'
// 5. 转换请求参数
const params = {
messages: [{ role: 'user' as const, content: 'Hello, AI!' }],
temperature: 0.7
}
const transformedParams = await pluginManager.executeSequential('transformParams', params, context)
// 6. 收集流转换器关键AI SDK 原生支持数组!)
const streamTransforms = pluginManager.collectStreamTransforms()
// 7. 调用 AI SDK直接传入转换器工厂数组
const result = await streamText({
model: openai('gpt-4'),
...transformedParams,
experimental_transform: streamTransforms // 直接传入工厂函数数组
})
// 8. 处理结果
let fullText = ''
for await (const textPart of result.textStream) {
fullText += textPart
console.log('Streaming:', textPart)
}
// 9. 转换最终结果
const finalResult = { text: fullText, usage: await result.usage }
const transformedResult = await pluginManager.executeSequential('transformResult', finalResult, context)
// 10. 触发完成事件
await pluginManager.executeParallel('onRequestEnd', context, transformedResult)
return transformedResult
} catch (error) {
// 11. 触发错误事件
await pluginManager.executeParallel('onError', context, undefined, error as Error)
throw error
}
}
/**
* 使
*/
export function demonstrateStreamTransforms() {
const pluginManager = new PluginManager([
ContentFilterPlugin,
{
name: 'text-replacer',
transformStream() {
return () =>
new TransformStream({
transform(chunk, controller) {
if (chunk.type === 'text-delta') {
const replaced = chunk.textDelta.replace(/hello/gi, 'hi')
controller.enqueue({ ...chunk, textDelta: replaced })
} else {
controller.enqueue(chunk)
}
}
})
}
}
])
// 获取所有流转换器
const transforms = pluginManager.collectStreamTransforms()
console.log(`收集到 ${transforms.length} 个流转换器`)
// 可以单独使用每个转换器
transforms.forEach((factory, index) => {
console.log(`转换器 ${index + 1} 已准备就绪`)
const transform = factory({ stopStream: () => {} })
console.log('Transform created:', transform)
})
return transforms
}

View File

@ -0,0 +1,255 @@
import { openai } from '@ai-sdk/openai'
import { streamText } from 'ai'
import { PluginEnabledAiClient } from '../../clients/PluginEnabledAiClient'
import { createContext, PluginManager } from '../'
import { ContentFilterPlugin, LoggingPlugin } from './example-plugins'
/**
* 使 PluginEnabledAiClient
* 使
*/
export async function exampleWithPluginEnabledClient() {
console.log('=== 使用 PluginEnabledAiClient 示例 ===')
// 1. 创建带插件的客户端 - 链式调用方式
const client = PluginEnabledAiClient.create('openai-compatible', {
name: 'openai',
baseURL: 'https://api.openai.com/v1',
apiKey: process.env.OPENAI_API_KEY || 'sk-test'
})
.use(LoggingPlugin)
.use(ContentFilterPlugin)
// 2. 或者在创建时传入插件(也可以这样使用)
// const clientWithPlugins = PluginEnabledAiClient.create(
// 'openai-compatible',
// {
// name: 'openai',
// baseURL: 'https://api.openai.com/v1',
// apiKey: process.env.OPENAI_API_KEY || 'sk-test'
// },
// [LoggingPlugin, ContentFilterPlugin]
// )
// 3. 查看插件统计信息
console.log('插件统计:', client.getPluginStats())
try {
// 4. 使用客户端进行 AI 调用(插件会自动生效)
console.log('开始生成文本...')
const result = await client.generateText('gpt-4', {
messages: [{ role: 'user', content: 'Hello, world!' }],
temperature: 0.7
})
console.log('生成的文本:', result.text)
// 5. 流式调用(支持流转换器)
console.log('开始流式生成...')
const streamResult = await client.streamText('gpt-4', {
messages: [{ role: 'user', content: 'Tell me a short story about AI' }]
})
console.log('开始流式响应...')
for await (const textPart of streamResult.textStream) {
process.stdout.write(textPart)
}
console.log('\n流式响应完成')
return result
} catch (error) {
console.error('调用失败:', error)
throw error
}
}
/**
* OpenAI Compatible
*/
export function exampleOpenAICompatible() {
console.log('=== OpenAI Compatible 示例 ===')
// Ollama 示例
const ollama = PluginEnabledAiClient.createOpenAICompatible(
{
name: 'ollama',
baseURL: 'http://localhost:11434/v1'
},
[LoggingPlugin]
)
// LM Studio 示例
const lmStudio = PluginEnabledAiClient.createOpenAICompatible({
name: 'lm-studio',
baseURL: 'http://localhost:1234/v1'
}).use(ContentFilterPlugin)
console.log('Ollama 插件统计:', ollama.getPluginStats())
console.log('LM Studio 插件统计:', lmStudio.getPluginStats())
return { ollama, lmStudio }
}
/**
*
*/
export function exampleDynamicPlugins() {
console.log('=== 动态插件管理示例 ===')
const client = PluginEnabledAiClient.create('openai-compatible', {
name: 'openai',
baseURL: 'https://api.openai.com/v1',
apiKey: 'your-api-key'
})
console.log('初始状态:', client.getPluginStats())
// 动态添加插件
client.use(LoggingPlugin)
console.log('添加 LoggingPlugin 后:', client.getPluginStats())
client.usePlugins([ContentFilterPlugin])
console.log('添加 ContentFilterPlugin 后:', client.getPluginStats())
// 移除插件
client.removePlugin('content-filter')
console.log('移除 content-filter 后:', client.getPluginStats())
return client
}
/**
* API example-usage.ts
*
*/
export async function exampleLowLevelApi() {
console.log('=== 低级 API 示例 ===')
// 1. 创建插件管理器
const pluginManager = new PluginManager([LoggingPlugin, ContentFilterPlugin])
// 2. 创建请求上下文
const context = createContext('openai', 'gpt-4', {
messages: [{ role: 'user', content: 'Hello!' }]
})
try {
// 3. 触发请求开始事件
await pluginManager.executeParallel('onRequestStart', context)
// 4. 解析模型别名
const resolvedModel = await pluginManager.executeFirst('resolveModel', 'gpt-4', context)
console.log('Resolved model:', resolvedModel || 'gpt-4')
// 5. 转换请求参数
const params = {
messages: [{ role: 'user' as const, content: 'Hello, AI!' }],
temperature: 0.7
}
const transformedParams = await pluginManager.executeSequential('transformParams', params, context)
// 6. 收集流转换器关键AI SDK 原生支持数组!)
const streamTransforms = pluginManager.collectStreamTransforms()
// 7. 调用 AI SDK直接传入转换器工厂数组
const result = await streamText({
model: openai('gpt-4'),
...transformedParams,
experimental_transform: streamTransforms // 直接传入工厂函数数组
})
// 8. 处理结果
let fullText = ''
for await (const textPart of result.textStream) {
fullText += textPart
console.log('Streaming:', textPart)
}
// 9. 转换最终结果
const finalResult = { text: fullText, usage: await result.usage }
const transformedResult = await pluginManager.executeSequential('transformResult', finalResult, context)
// 10. 触发完成事件
await pluginManager.executeParallel('onRequestEnd', context, transformedResult)
return transformedResult
} catch (error) {
// 11. 触发错误事件
await pluginManager.executeParallel('onError', context, undefined, error as Error)
throw error
}
}
/**
* 使
*/
export function demonstrateStreamTransforms() {
console.log('=== 流转换器示例 ===')
const pluginManager = new PluginManager([
ContentFilterPlugin,
{
name: 'text-replacer',
transformStream() {
return () =>
new TransformStream({
transform(chunk, controller) {
if (chunk.type === 'text-delta') {
const replaced = chunk.textDelta.replace(/hello/gi, 'hi')
controller.enqueue({ ...chunk, textDelta: replaced })
} else {
controller.enqueue(chunk)
}
}
})
}
}
])
// 获取所有流转换器
const transforms = pluginManager.collectStreamTransforms()
console.log(`收集到 ${transforms.length} 个流转换器`)
// 可以单独使用每个转换器
transforms.forEach((factory, index) => {
console.log(`转换器 ${index + 1} 已准备就绪`)
const transform = factory({ stopStream: () => {} })
console.log('Transform created:', transform)
})
return transforms
}
/**
*
*/
export async function runAllExamples() {
console.log('🚀 开始运行所有示例...\n')
try {
// 1. PluginEnabledAiClient 示例(推荐)
await exampleWithPluginEnabledClient()
console.log('✅ PluginEnabledAiClient 示例完成\n')
// 2. OpenAI Compatible 示例
exampleOpenAICompatible()
console.log('✅ OpenAI Compatible 示例完成\n')
// 3. 动态插件管理示例
exampleDynamicPlugins()
console.log('✅ 动态插件管理示例完成\n')
// 4. 流转换器示例
demonstrateStreamTransforms()
console.log('✅ 流转换器示例完成\n')
// 5. 低级 API 示例
// await exampleLowLevelApi()
console.log('✅ 低级 API 示例完成\n')
console.log('🎉 所有示例运行完成!')
} catch (error) {
console.error('❌ 示例运行失败:', error)
}
}

View File

@ -1,5 +1,28 @@
import type { TextStreamPart, ToolSet } from 'ai'
/**
*
*/
export enum LifecycleStage {
PRE_REQUEST = 'pre-request', // 请求预处理
REQUEST_EXECUTION = 'execution', // 请求执行
STREAM_PROCESSING = 'stream', // 流式处理(仅流模式)
POST_RESPONSE = 'post-response', // 响应后处理
ERROR_HANDLING = 'error' // 错误处理
}
/**
*
*/
export interface LifecycleContext {
currentStage: LifecycleStage
startTime: number
stageStartTime: number
completedStages: Set<LifecycleStage>
stageDurations: Map<LifecycleStage, number>
metadata: Record<string, any>
}
/**
* AI
*/

View File

@ -1,9 +1,67 @@
/**
* AI Provider
* AI SDK Providers
* +
*/
// Provider 配置接口(简化版)
// 静态导入所有 AI SDK 类型
import { type AmazonBedrockProviderSettings } from '@ai-sdk/amazon-bedrock'
import { type AnthropicProviderSettings } from '@ai-sdk/anthropic'
import { type AzureOpenAIProviderSettings } from '@ai-sdk/azure'
import { type CerebrasProviderSettings } from '@ai-sdk/cerebras'
import { type CohereProviderSettings } from '@ai-sdk/cohere'
import { type DeepInfraProviderSettings } from '@ai-sdk/deepinfra'
import { type DeepSeekProviderSettings } from '@ai-sdk/deepseek'
import { type FalProviderSettings } from '@ai-sdk/fal'
import { type FireworksProviderSettings } from '@ai-sdk/fireworks'
import { type GoogleGenerativeAIProviderSettings } from '@ai-sdk/google'
import { type GoogleVertexProviderSettings } from '@ai-sdk/google-vertex'
import { type GroqProviderSettings } from '@ai-sdk/groq'
import { type MistralProviderSettings } from '@ai-sdk/mistral'
import { type OpenAIProviderSettings } from '@ai-sdk/openai'
import { type OpenAICompatibleProviderSettings } from '@ai-sdk/openai-compatible'
import { type PerplexityProviderSettings } from '@ai-sdk/perplexity'
import { type ReplicateProviderSettings } from '@ai-sdk/replicate'
import { type TogetherAIProviderSettings } from '@ai-sdk/togetherai'
import { type VercelProviderSettings } from '@ai-sdk/vercel'
import { type XaiProviderSettings } from '@ai-sdk/xai'
import { type OpenRouterProviderSettings } from '@openrouter/ai-sdk-provider'
import { type AnthropicVertexProviderSettings } from 'anthropic-vertex-ai'
import { type OllamaProviderSettings } from 'ollama-ai-provider'
import { type QwenProviderSettings } from 'qwen-ai-provider'
import { type ZhipuProviderSettings } from 'zhipu-ai-provider'
// 类型安全的 Provider Settings 映射
export type ProviderSettingsMap = {
openai: OpenAIProviderSettings
'openai-compatible': OpenAICompatibleProviderSettings
anthropic: AnthropicProviderSettings
google: GoogleGenerativeAIProviderSettings
'google-vertex': GoogleVertexProviderSettings
mistral: MistralProviderSettings
xai: XaiProviderSettings
azure: AzureOpenAIProviderSettings
bedrock: AmazonBedrockProviderSettings
cohere: CohereProviderSettings
groq: GroqProviderSettings
together: TogetherAIProviderSettings
fireworks: FireworksProviderSettings
deepseek: DeepSeekProviderSettings
cerebras: CerebrasProviderSettings
deepinfra: DeepInfraProviderSettings
replicate: ReplicateProviderSettings
perplexity: PerplexityProviderSettings
fal: FalProviderSettings
vercel: VercelProviderSettings
ollama: OllamaProviderSettings
qwen: QwenProviderSettings
zhipu: ZhipuProviderSettings
'anthropic-vertex': AnthropicVertexProviderSettings
openrouter: OpenRouterProviderSettings
}
export type ProviderId = keyof ProviderSettingsMap
// 统一的 Provider 配置接口(所有都使用动态导入)
export interface ProviderConfig {
id: string
name: string
@ -38,7 +96,7 @@ export class AiProviderRegistry {
*/
private initializeProviders(): void {
const providers: ProviderConfig[] = [
// 核心 AI SDK Providers
// 官方 AI SDK Providers (19个)
{
id: 'openai',
name: 'OpenAI',
@ -158,11 +216,9 @@ export class AiProviderRegistry {
name: 'Vercel',
import: () => import('@ai-sdk/vercel'),
creatorFunctionName: 'createVercel'
}
]
},
// 社区提供的 Providers
const communityProviders: ProviderConfig[] = [
// 社区 Providers (5个)
{
id: 'ollama',
name: 'Ollama',
@ -195,9 +251,8 @@ export class AiProviderRegistry {
}
]
// 注册所有 providers官方 + 社区)
const allProviders = [...providers, ...communityProviders]
allProviders.forEach((config) => {
// 注册所有 providers (总计24个)
providers.forEach((config) => {
this.registry.set(config.id, config)
})
}
@ -265,3 +320,32 @@ export const registerProvider = (config: ProviderConfig) => aiProviderRegistry.r
// 兼容现有实现的导出
export const PROVIDER_REGISTRY = aiProviderRegistry.getCompatibleRegistry()
// 重新导出所有类型供外部使用
export type {
AmazonBedrockProviderSettings,
AnthropicProviderSettings,
AnthropicVertexProviderSettings,
AzureOpenAIProviderSettings,
CerebrasProviderSettings,
CohereProviderSettings,
DeepInfraProviderSettings,
DeepSeekProviderSettings,
FalProviderSettings,
FireworksProviderSettings,
GoogleGenerativeAIProviderSettings,
GoogleVertexProviderSettings,
GroqProviderSettings,
MistralProviderSettings,
OllamaProviderSettings,
OpenAICompatibleProviderSettings,
OpenAIProviderSettings,
OpenRouterProviderSettings,
PerplexityProviderSettings,
QwenProviderSettings,
ReplicateProviderSettings,
TogetherAIProviderSettings,
VercelProviderSettings,
XaiProviderSettings,
ZhipuProviderSettings
}

View File

@ -1,66 +0,0 @@
/**
* AI Core
* 使 Vercel AI SDK
*/
// 直接重新导出 AI SDK 的类型,避免重复定义
export type {
// 通用类型
CoreMessage,
CoreTool,
CoreToolChoice,
// 其他有用的类型
FinishReason,
GenerateTextResult,
LanguageModelV1,
// 核心函数的参数和返回类型
StreamTextResult,
// 流式处理相关
TextStreamPart,
ToolSet
} from 'ai'
/**
*
*/
export enum LifecycleStage {
PRE_REQUEST = 'pre-request', // 请求预处理
REQUEST_EXECUTION = 'execution', // 请求执行
STREAM_PROCESSING = 'stream', // 流式处理(仅流模式)
POST_RESPONSE = 'post-response', // 响应后处理
ERROR_HANDLING = 'error' // 错误处理
}
/**
*
*/
export interface LifecycleContext {
currentStage: LifecycleStage
startTime: number
stageStartTime: number
completedStages: Set<LifecycleStage>
stageDurations: Map<LifecycleStage, number>
metadata: Record<string, any>
}
/**
*
*/
export interface AiRequestContext {
// 生命周期信息
lifecycle: LifecycleContext
// 请求信息
method: 'streamText' | 'generateText'
providerId: string
originalParams: any // 使用 any让 AI SDK 自己处理类型检查
// 可变状态
state: {
transformedParams?: any
result?: any
error?: Error
aborted?: boolean
metadata: Record<string, any>
}
}

496
yarn.lock
View File

@ -241,7 +241,7 @@ __metadata:
languageName: node
linkType: hard
"@ai-sdk/openai-compatible@npm:0.2.14":
"@ai-sdk/openai-compatible@npm:0.2.14, @ai-sdk/openai-compatible@npm:^0.2.14":
version: 0.2.14
resolution: "@ai-sdk/openai-compatible@npm:0.2.14"
dependencies:
@ -311,6 +311,23 @@ __metadata:
languageName: node
linkType: hard
"@ai-sdk/provider-utils@npm:2.1.5":
version: 2.1.5
resolution: "@ai-sdk/provider-utils@npm:2.1.5"
dependencies:
"@ai-sdk/provider": "npm:1.0.6"
eventsource-parser: "npm:^3.0.0"
nanoid: "npm:^3.3.8"
secure-json-parse: "npm:^2.7.0"
peerDependencies:
zod: ^3.0.0
peerDependenciesMeta:
zod:
optional: true
checksum: 10c0/6ec33c1f9cc6bb38a7634cdb1b43f49d78ddcb92a8daa4b65193f3309b5a7ad35b134e2d5e82b8576917079a3f8e3b83b5505151cd259ec747ba27458db58356
languageName: node
linkType: hard
"@ai-sdk/provider-utils@npm:2.2.8, @ai-sdk/provider-utils@npm:^2.0.0, @ai-sdk/provider-utils@npm:^2.1.6":
version: 2.2.8
resolution: "@ai-sdk/provider-utils@npm:2.2.8"
@ -333,6 +350,15 @@ __metadata:
languageName: node
linkType: hard
"@ai-sdk/provider@npm:1.0.6":
version: 1.0.6
resolution: "@ai-sdk/provider@npm:1.0.6"
dependencies:
json-schema: "npm:^0.4.0"
checksum: 10c0/251c8cd4fa53b89dcf751d0faba5482762d88fcc5ffe1cdb660327c14817a4d94206317e95e6e69fc4ae3071001191b5c418b4b9e1212d6a554a90114db216fc
languageName: node
linkType: hard
"@ai-sdk/provider@npm:1.0.9":
version: 1.0.9
resolution: "@ai-sdk/provider@npm:1.0.9"
@ -684,6 +710,19 @@ __metadata:
languageName: node
linkType: hard
"@babel/generator@npm:^7.27.5":
version: 7.27.5
resolution: "@babel/generator@npm:7.27.5"
dependencies:
"@babel/parser": "npm:^7.27.5"
"@babel/types": "npm:^7.27.3"
"@jridgewell/gen-mapping": "npm:^0.3.5"
"@jridgewell/trace-mapping": "npm:^0.3.25"
jsesc: "npm:^3.0.2"
checksum: 10c0/8f649ef4cd81765c832bb11de4d6064b035ffebdecde668ba7abee68a7b0bce5c9feabb5dc5bb8aeba5bd9e5c2afa3899d852d2bd9ca77a711ba8c8379f416f0
languageName: node
linkType: hard
"@babel/helper-compilation-targets@npm:^7.26.5":
version: 7.27.0
resolution: "@babel/helper-compilation-targets@npm:7.27.0"
@ -794,6 +833,17 @@ __metadata:
languageName: node
linkType: hard
"@babel/parser@npm:^7.27.3, @babel/parser@npm:^7.27.5":
version: 7.27.5
resolution: "@babel/parser@npm:7.27.5"
dependencies:
"@babel/types": "npm:^7.27.3"
bin:
parser: ./bin/babel-parser.js
checksum: 10c0/f7faaebf21cc1f25d9ca8ac02c447ed38ef3460ea95be7ea760916dcf529476340d72a5a6010c6641d9ed9d12ad827c8424840277ec2295c5b082ba0f291220a
languageName: node
linkType: hard
"@babel/plugin-transform-arrow-functions@npm:^7.25.9":
version: 7.25.9
resolution: "@babel/plugin-transform-arrow-functions@npm:7.25.9"
@ -867,6 +917,16 @@ __metadata:
languageName: node
linkType: hard
"@babel/types@npm:^7.27.3, @babel/types@npm:^7.27.6":
version: 7.27.6
resolution: "@babel/types@npm:7.27.6"
dependencies:
"@babel/helper-string-parser": "npm:^7.27.1"
"@babel/helper-validator-identifier": "npm:^7.27.1"
checksum: 10c0/39d556be114f2a6d874ea25ad39826a9e3a0e98de0233ae6d932f6d09a4b222923a90a7274c635ed61f1ba49bbd345329226678800900ad1c8d11afabd573aaf
languageName: node
linkType: hard
"@bcoe/v8-coverage@npm:^1.0.2":
version: 1.0.2
resolution: "@bcoe/v8-coverage@npm:1.0.2"
@ -918,15 +978,18 @@ __metadata:
"@ai-sdk/groq": "npm:^1.2.9"
"@ai-sdk/mistral": "npm:^1.2.8"
"@ai-sdk/openai": "npm:^1.3.22"
"@ai-sdk/openai-compatible": "npm:^0.2.14"
"@ai-sdk/perplexity": "npm:^1.1.9"
"@ai-sdk/replicate": "npm:^0.2.8"
"@ai-sdk/togetherai": "npm:^0.2.14"
"@ai-sdk/vercel": "npm:^0.0.1"
"@ai-sdk/xai": "npm:^1.2.16"
"@openrouter/ai-sdk-provider": "npm:^0.1.0"
ai: "npm:^4.3.16"
anthropic-vertex-ai: "npm:^1.0.2"
ollama-ai-provider: "npm:^1.2.0"
qwen-ai-provider: "npm:^0.1.0"
tsdown: "npm:^0.12.8"
typescript: "npm:^5.0.0"
zhipu-ai-provider: "npm:^0.1.1"
peerDependenciesMeta:
@ -1869,6 +1932,34 @@ __metadata:
languageName: node
linkType: hard
"@emnapi/core@npm:^1.4.3":
version: 1.4.3
resolution: "@emnapi/core@npm:1.4.3"
dependencies:
"@emnapi/wasi-threads": "npm:1.0.2"
tslib: "npm:^2.4.0"
checksum: 10c0/e30101d16d37ef3283538a35cad60e22095aff2403fb9226a35330b932eb6740b81364d525537a94eb4fb51355e48ae9b10d779c0dd1cdcd55d71461fe4b45c7
languageName: node
linkType: hard
"@emnapi/runtime@npm:^1.4.3":
version: 1.4.3
resolution: "@emnapi/runtime@npm:1.4.3"
dependencies:
tslib: "npm:^2.4.0"
checksum: 10c0/3b7ab72d21cb4e034f07df80165265f85f445ef3f581d1bc87b67e5239428baa00200b68a7d5e37a0425c3a78320b541b07f76c5530f6f6f95336a6294ebf30b
languageName: node
linkType: hard
"@emnapi/wasi-threads@npm:1.0.2":
version: 1.0.2
resolution: "@emnapi/wasi-threads@npm:1.0.2"
dependencies:
tslib: "npm:^2.4.0"
checksum: 10c0/f0621b1fc715221bd2d8332c0ca922617bcd77cdb3050eae50a124eb8923c54fa425d23982dc8f29d505c8798a62d1049bace8b0686098ff9dd82270e06d772e
languageName: node
linkType: hard
"@emotion/hash@npm:^0.8.0":
version: 0.8.0
resolution: "@emotion/hash@npm:0.8.0"
@ -3531,6 +3622,17 @@ __metadata:
languageName: node
linkType: hard
"@napi-rs/wasm-runtime@npm:^0.2.10":
version: 0.2.11
resolution: "@napi-rs/wasm-runtime@npm:0.2.11"
dependencies:
"@emnapi/core": "npm:^1.4.3"
"@emnapi/runtime": "npm:^1.4.3"
"@tybys/wasm-util": "npm:^0.9.0"
checksum: 10c0/049bd14c58b99fbe0967b95e9921c5503df196b59be22948d2155f17652eb305cff6728efd8685338b855da7e476dd2551fbe3a313fc2d810938f0717478441e
languageName: node
linkType: hard
"@neon-rs/load@npm:^0.0.4":
version: 0.0.4
resolution: "@neon-rs/load@npm:0.0.4"
@ -3646,6 +3748,18 @@ __metadata:
languageName: node
linkType: hard
"@openrouter/ai-sdk-provider@npm:^0.1.0":
version: 0.1.0
resolution: "@openrouter/ai-sdk-provider@npm:0.1.0"
dependencies:
"@ai-sdk/provider": "npm:1.0.6"
"@ai-sdk/provider-utils": "npm:2.1.5"
peerDependencies:
zod: ^3.0.0
checksum: 10c0/495c0349d6f42adc8e880651c215a183a4f041808019c6b2710df447ff3c81f5e69f951b589c1bb3c0cc1ce16c0d659b624d18f097b3344bce74eb178fb936a1
languageName: node
linkType: hard
"@opentelemetry/api@npm:1.9.0":
version: 1.9.0
resolution: "@opentelemetry/api@npm:1.9.0"
@ -3653,6 +3767,20 @@ __metadata:
languageName: node
linkType: hard
"@oxc-project/runtime@npm:=0.72.3":
version: 0.72.3
resolution: "@oxc-project/runtime@npm:0.72.3"
checksum: 10c0/35d3be02bbb12252529585483c8fa64bb0e44fb55cf20d0763eb9cc9fe1b9033777125ba768fb7bce8e4776a48f5a175e9ef324575f0932048482c0477799ac8
languageName: node
linkType: hard
"@oxc-project/types@npm:=0.72.3":
version: 0.72.3
resolution: "@oxc-project/types@npm:0.72.3"
checksum: 10c0/8c1379671895b3ad3215d13a8194fc19150b16b35ad47b753c25963650055da9f11dade0225d6c522771f038451aff687e9fb9efdea5486ede5880631316c9f7
languageName: node
linkType: hard
"@parcel/watcher-android-arm64@npm:2.5.1":
version: 2.5.1
resolution: "@parcel/watcher-android-arm64@npm:2.5.1"
@ -3829,6 +3957,15 @@ __metadata:
languageName: node
linkType: hard
"@quansync/fs@npm:^0.1.1":
version: 0.1.3
resolution: "@quansync/fs@npm:0.1.3"
dependencies:
quansync: "npm:^0.2.10"
checksum: 10c0/15d9914328d296df6626b6b2d5e9f455f618d5c8ffff09270ca3ce42c1bd21e4a91b53d6c1d857fbcae3be8c07b33ab82a83532870f2c5bf74904fe0ac60a3d1
languageName: node
linkType: hard
"@rc-component/async-validator@npm:^5.0.3":
version: 5.0.4
resolution: "@rc-component/async-validator@npm:5.0.4"
@ -4037,6 +4174,99 @@ __metadata:
languageName: node
linkType: hard
"@rolldown/binding-darwin-arm64@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-darwin-arm64@npm:1.0.0-beta.15"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@rolldown/binding-darwin-x64@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-darwin-x64@npm:1.0.0-beta.15"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@rolldown/binding-freebsd-x64@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-freebsd-x64@npm:1.0.0-beta.15"
conditions: os=freebsd & cpu=x64
languageName: node
linkType: hard
"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-beta.15"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.0.0-beta.15"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@rolldown/binding-linux-arm64-musl@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-linux-arm64-musl@npm:1.0.0-beta.15"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@rolldown/binding-linux-x64-gnu@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-linux-x64-gnu@npm:1.0.0-beta.15"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@rolldown/binding-linux-x64-musl@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-linux-x64-musl@npm:1.0.0-beta.15"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@rolldown/binding-wasm32-wasi@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-wasm32-wasi@npm:1.0.0-beta.15"
dependencies:
"@napi-rs/wasm-runtime": "npm:^0.2.10"
conditions: cpu=wasm32
languageName: node
linkType: hard
"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.0.0-beta.15"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@rolldown/binding-win32-ia32-msvc@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-win32-ia32-msvc@npm:1.0.0-beta.15"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
"@rolldown/binding-win32-x64-msvc@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/binding-win32-x64-msvc@npm:1.0.0-beta.15"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@rolldown/pluginutils@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "@rolldown/pluginutils@npm:1.0.0-beta.15"
checksum: 10c0/9e6dad8d82a34db600ef78f8da243e9f00f2b873afef9e071fd2bc1a26d9eb5cb9da474f211c42caabb8f6fcaf9bfbecc7e69af113aa84419967f012eb3228f3
languageName: node
linkType: hard
"@rollup/rollup-android-arm-eabi@npm:4.40.0":
version: 4.40.0
resolution: "@rollup/rollup-android-arm-eabi@npm:4.40.0"
@ -4651,6 +4881,15 @@ __metadata:
languageName: node
linkType: hard
"@tybys/wasm-util@npm:^0.9.0":
version: 0.9.0
resolution: "@tybys/wasm-util@npm:0.9.0"
dependencies:
tslib: "npm:^2.4.0"
checksum: 10c0/f9fde5c554455019f33af6c8215f1a1435028803dc2a2825b077d812bed4209a1a64444a4ca0ce2ea7e1175c8d88e2f9173a36a33c199e8a5c671aa31de8242d
languageName: node
linkType: hard
"@types/aria-query@npm:^5.0.1":
version: 5.0.4
resolution: "@types/aria-query@npm:5.0.4"
@ -6508,6 +6747,13 @@ __metadata:
languageName: node
linkType: hard
"ansis@npm:^4.0.0, ansis@npm:^4.1.0":
version: 4.1.0
resolution: "ansis@npm:4.1.0"
checksum: 10c0/df62d017a7791babdaf45b93f930d2cfd6d1dab5568b610735c11434c9a5ef8f513740e7cfd80bcbc3530fc8bd892b88f8476f26621efc251230e53cbd1a2c24
languageName: node
linkType: hard
"antd@npm:^5.22.5":
version: 5.24.7
resolution: "antd@npm:5.24.7"
@ -6769,6 +7015,16 @@ __metadata:
languageName: node
linkType: hard
"ast-kit@npm:^2.1.0":
version: 2.1.0
resolution: "ast-kit@npm:2.1.0"
dependencies:
"@babel/parser": "npm:^7.27.3"
pathe: "npm:^2.0.3"
checksum: 10c0/67246f34745f40b6a5bee2467a1a00f7f006a051f80d7cda7e3b7fe5f7d7a1f262521b72643fcbffb21d33f36aa59868636229a769b2802355d687815ad7b13d
languageName: node
linkType: hard
"ast-types@npm:^0.13.4":
version: 0.13.4
resolution: "ast-types@npm:0.13.4"
@ -6924,6 +7180,13 @@ __metadata:
languageName: node
linkType: hard
"birpc@npm:^2.3.0":
version: 2.4.0
resolution: "birpc@npm:2.4.0"
checksum: 10c0/6ecda217b540189221913f215055baf4f10f264a1a8f0000ef6db3ecb0ccc5e4fde135b5f0719c389f1a593e64af3041404019711225ab31badf23c2a98d7778
languageName: node
linkType: hard
"bl@npm:^1.0.0":
version: 1.2.3
resolution: "bl@npm:1.2.3"
@ -7435,7 +7698,7 @@ __metadata:
languageName: node
linkType: hard
"chokidar@npm:^4.0.0":
"chokidar@npm:^4.0.0, chokidar@npm:^4.0.3":
version: 4.0.3
resolution: "chokidar@npm:4.0.3"
dependencies:
@ -8472,6 +8735,18 @@ __metadata:
languageName: node
linkType: hard
"debug@npm:^4.4.1":
version: 4.4.1
resolution: "debug@npm:4.4.1"
dependencies:
ms: "npm:^2.1.3"
peerDependenciesMeta:
supports-color:
optional: true
checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55
languageName: node
linkType: hard
"decamelize@npm:1.2.0":
version: 1.2.0
resolution: "decamelize@npm:1.2.0"
@ -8661,6 +8936,13 @@ __metadata:
languageName: node
linkType: hard
"defu@npm:^6.1.4":
version: 6.1.4
resolution: "defu@npm:6.1.4"
checksum: 10c0/2d6cc366262dc0cb8096e429368e44052fdf43ed48e53ad84cc7c9407f890301aa5fcb80d0995abaaf842b3949f154d060be4160f7a46cb2bc2f7726c81526f5
languageName: node
linkType: hard
"degenerator@npm:^5.0.0":
version: 5.0.1
resolution: "degenerator@npm:5.0.1"
@ -8787,6 +9069,13 @@ __metadata:
languageName: node
linkType: hard
"diff@npm:^8.0.2":
version: 8.0.2
resolution: "diff@npm:8.0.2"
checksum: 10c0/abfb387f033e089df3ec3be960205d17b54df8abf0924d982a7ced3a94c557a4e6cbff2e78b121f216b85f466b3d8d041673a386177c311aaea41459286cc9bc
languageName: node
linkType: hard
"dingbat-to-unicode@npm:^1.0.1":
version: 1.0.1
resolution: "dingbat-to-unicode@npm:1.0.1"
@ -8964,6 +9253,18 @@ __metadata:
languageName: node
linkType: hard
"dts-resolver@npm:^2.1.1":
version: 2.1.1
resolution: "dts-resolver@npm:2.1.1"
peerDependencies:
oxc-resolver: ">=11.0.0"
peerDependenciesMeta:
oxc-resolver:
optional: true
checksum: 10c0/bc36d71822d39f23cfe274b6781fae4b1729bd8b0a07e4a011fe243a73c5dbbb30ea067fb0d6248fdfedc29cf4dfc0ff19f0dd38950158444409d109c1c55b7e
languageName: node
linkType: hard
"duck@npm:^0.1.12":
version: 0.1.12
resolution: "duck@npm:0.1.12"
@ -9187,6 +9488,13 @@ __metadata:
languageName: node
linkType: hard
"empathic@npm:^1.1.0":
version: 1.1.0
resolution: "empathic@npm:1.1.0"
checksum: 10c0/ed906c4ad6dabe1477ed00d6420f79eff8ac72e2eb580aab42406f50160fd34d66e8381e92b405e96d75a826a840706af261fd397c3e7db4d1a293d23e2e72f7
languageName: node
linkType: hard
"encodeurl@npm:^2.0.0":
version: 2.0.0
resolution: "encodeurl@npm:2.0.0"
@ -10752,6 +11060,15 @@ __metadata:
languageName: node
linkType: hard
"get-tsconfig@npm:^4.10.1":
version: 4.10.1
resolution: "get-tsconfig@npm:4.10.1"
dependencies:
resolve-pkg-maps: "npm:^1.0.0"
checksum: 10c0/7f8e3dabc6a49b747920a800fb88e1952fef871cdf51b79e98db48275a5de6cdaf499c55ee67df5fa6fe7ce65f0063e26de0f2e53049b408c585aa74d39ffa21
languageName: node
linkType: hard
"get-uri@npm:^6.0.1":
version: 6.0.4
resolution: "get-uri@npm:6.0.4"
@ -11230,6 +11547,13 @@ __metadata:
languageName: node
linkType: hard
"hookable@npm:^5.5.3":
version: 5.5.3
resolution: "hookable@npm:5.5.3"
checksum: 10c0/275f4cc84d27f8d48c5a5cd5685b6c0fea9291be9deea5bff0cfa72856ed566abde1dcd8cb1da0f9a70b4da3d7ec0d60dc3554c4edbba647058cc38816eced3d
languageName: node
linkType: hard
"hosted-git-info@npm:^4.1.0":
version: 4.1.0
resolution: "hosted-git-info@npm:4.1.0"
@ -11963,6 +12287,15 @@ __metadata:
languageName: node
linkType: hard
"jiti@npm:^2.4.2":
version: 2.4.2
resolution: "jiti@npm:2.4.2"
bin:
jiti: lib/jiti-cli.mjs
checksum: 10c0/4ceac133a08c8faff7eac84aabb917e85e8257f5ad659e843004ce76e981c457c390a220881748ac67ba1b940b9b729b30fb85cbaf6e7989f04b6002c94da331
languageName: node
linkType: hard
"js-base64@npm:^3.7.5":
version: 3.7.7
resolution: "js-base64@npm:3.7.7"
@ -15585,7 +15918,7 @@ __metadata:
languageName: node
linkType: hard
"quansync@npm:^0.2.8":
"quansync@npm:^0.2.10, quansync@npm:^0.2.8":
version: 0.2.10
resolution: "quansync@npm:0.2.10"
checksum: 10c0/f86f1d644f812a3a7c42de79eb401c47a5a67af82a9adff8a8afb159325e03e00f77cebbf42af6340a0bd47bd0c1fbe999e7caf7e1bbb30d7acb00c8729b7530
@ -16794,6 +17127,13 @@ __metadata:
languageName: node
linkType: hard
"resolve-pkg-maps@npm:^1.0.0":
version: 1.0.0
resolution: "resolve-pkg-maps@npm:1.0.0"
checksum: 10c0/fb8f7bbe2ca281a73b7ef423a1cbc786fb244bd7a95cbe5c3fba25b27d327150beca8ba02f622baea65919a57e061eb5005204daa5f93ed590d9b77463a567ab
languageName: node
linkType: hard
"responselike@npm:^2.0.0":
version: 2.0.1
resolution: "responselike@npm:2.0.1"
@ -16903,6 +17243,85 @@ __metadata:
languageName: node
linkType: hard
"rolldown-plugin-dts@npm:^0.13.11":
version: 0.13.11
resolution: "rolldown-plugin-dts@npm:0.13.11"
dependencies:
"@babel/generator": "npm:^7.27.5"
"@babel/parser": "npm:^7.27.5"
"@babel/types": "npm:^7.27.6"
ast-kit: "npm:^2.1.0"
birpc: "npm:^2.3.0"
debug: "npm:^4.4.1"
dts-resolver: "npm:^2.1.1"
get-tsconfig: "npm:^4.10.1"
peerDependencies:
"@typescript/native-preview": ">=7.0.0-dev.20250601.1"
rolldown: ^1.0.0-beta.9
typescript: ^5.0.0
vue-tsc: ~2.2.0
peerDependenciesMeta:
"@typescript/native-preview":
optional: true
typescript:
optional: true
vue-tsc:
optional: true
checksum: 10c0/026cda47fd0b4d79e51e5dad0aca02749092ab006ac9317d153a42620cfd7f613ed075da3828aa37f49bec585c7871b5c997ed699385b9f326314004bf5c71e0
languageName: node
linkType: hard
"rolldown@npm:1.0.0-beta.15":
version: 1.0.0-beta.15
resolution: "rolldown@npm:1.0.0-beta.15"
dependencies:
"@oxc-project/runtime": "npm:=0.72.3"
"@oxc-project/types": "npm:=0.72.3"
"@rolldown/binding-darwin-arm64": "npm:1.0.0-beta.15"
"@rolldown/binding-darwin-x64": "npm:1.0.0-beta.15"
"@rolldown/binding-freebsd-x64": "npm:1.0.0-beta.15"
"@rolldown/binding-linux-arm-gnueabihf": "npm:1.0.0-beta.15"
"@rolldown/binding-linux-arm64-gnu": "npm:1.0.0-beta.15"
"@rolldown/binding-linux-arm64-musl": "npm:1.0.0-beta.15"
"@rolldown/binding-linux-x64-gnu": "npm:1.0.0-beta.15"
"@rolldown/binding-linux-x64-musl": "npm:1.0.0-beta.15"
"@rolldown/binding-wasm32-wasi": "npm:1.0.0-beta.15"
"@rolldown/binding-win32-arm64-msvc": "npm:1.0.0-beta.15"
"@rolldown/binding-win32-ia32-msvc": "npm:1.0.0-beta.15"
"@rolldown/binding-win32-x64-msvc": "npm:1.0.0-beta.15"
"@rolldown/pluginutils": "npm:1.0.0-beta.15"
ansis: "npm:^4.0.0"
dependenciesMeta:
"@rolldown/binding-darwin-arm64":
optional: true
"@rolldown/binding-darwin-x64":
optional: true
"@rolldown/binding-freebsd-x64":
optional: true
"@rolldown/binding-linux-arm-gnueabihf":
optional: true
"@rolldown/binding-linux-arm64-gnu":
optional: true
"@rolldown/binding-linux-arm64-musl":
optional: true
"@rolldown/binding-linux-x64-gnu":
optional: true
"@rolldown/binding-linux-x64-musl":
optional: true
"@rolldown/binding-wasm32-wasi":
optional: true
"@rolldown/binding-win32-arm64-msvc":
optional: true
"@rolldown/binding-win32-ia32-msvc":
optional: true
"@rolldown/binding-win32-x64-msvc":
optional: true
bin:
rolldown: bin/cli.mjs
checksum: 10c0/de2ea888c85ce458232707b75c9e8982ee128c497d0e5c992b4085c57bdd36bcc73d04f3fba3186ab70274288d6914c94f280ab380ce0b4347610b51b82e25e8
languageName: node
linkType: hard
"rollup-plugin-visualizer@npm:^5.12.0":
version: 5.14.0
resolution: "rollup-plugin-visualizer@npm:5.14.0"
@ -17199,6 +17618,15 @@ __metadata:
languageName: node
linkType: hard
"semver@npm:^7.7.2":
version: 7.7.2
resolution: "semver@npm:7.7.2"
bin:
semver: bin/semver.js
checksum: 10c0/aca305edfbf2383c22571cb7714f48cadc7ac95371b4b52362fb8eeffdfbc0de0669368b82b2b15978f8848f01d7114da65697e56cd8c37b0dab8c58e543f9ea
languageName: node
linkType: hard
"send@npm:^1.1.0, send@npm:^1.2.0":
version: 1.2.0
resolution: "send@npm:1.2.0"
@ -18163,6 +18591,16 @@ __metadata:
languageName: node
linkType: hard
"tinyglobby@npm:^0.2.14":
version: 0.2.14
resolution: "tinyglobby@npm:0.2.14"
dependencies:
fdir: "npm:^6.4.4"
picomatch: "npm:^4.0.2"
checksum: 10c0/f789ed6c924287a9b7d3612056ed0cda67306cd2c80c249fd280cf1504742b12583a2089b61f4abbd24605f390809017240e250241f09938054c9b363e51c0a6
languageName: node
linkType: hard
"tinypool@npm:^1.0.2":
version: 1.0.2
resolution: "tinypool@npm:1.0.2"
@ -18381,6 +18819,46 @@ __metadata:
languageName: node
linkType: hard
"tsdown@npm:^0.12.8":
version: 0.12.8
resolution: "tsdown@npm:0.12.8"
dependencies:
ansis: "npm:^4.1.0"
cac: "npm:^6.7.14"
chokidar: "npm:^4.0.3"
debug: "npm:^4.4.1"
diff: "npm:^8.0.2"
empathic: "npm:^1.1.0"
hookable: "npm:^5.5.3"
rolldown: "npm:1.0.0-beta.15"
rolldown-plugin-dts: "npm:^0.13.11"
semver: "npm:^7.7.2"
tinyexec: "npm:^1.0.1"
tinyglobby: "npm:^0.2.14"
unconfig: "npm:^7.3.2"
peerDependencies:
"@arethetypeswrong/core": ^0.18.1
publint: ^0.3.0
typescript: ^5.0.0
unplugin-lightningcss: ^0.4.0
unplugin-unused: ^0.5.0
peerDependenciesMeta:
"@arethetypeswrong/core":
optional: true
publint:
optional: true
typescript:
optional: true
unplugin-lightningcss:
optional: true
unplugin-unused:
optional: true
bin:
tsdown: dist/run.mjs
checksum: 10c0/8b824da2cdabbd9a783ac9d5d71a70d17ee055b614cf95070180b061f4b4d422c66795c6e871da67aa0ce15355d82dc97cb86f126d38f8af5c088959107a8fc9
languageName: node
linkType: hard
"tslib@npm:2.6.2":
version: 2.6.2
resolution: "tslib@npm:2.6.2"
@ -18512,6 +18990,18 @@ __metadata:
languageName: node
linkType: hard
"unconfig@npm:^7.3.2":
version: 7.3.2
resolution: "unconfig@npm:7.3.2"
dependencies:
"@quansync/fs": "npm:^0.1.1"
defu: "npm:^6.1.4"
jiti: "npm:^2.4.2"
quansync: "npm:^0.2.8"
checksum: 10c0/245a0add92413b9a04a0bad879c7ee4d6904e58c9d091dbb1ea89fb7491d22d0f2ad17bd561329e006cb1954b5ece00f4cd9f9300a72af5013a927dc7fd5d27b
languageName: node
linkType: hard
"underscore@npm:^1.13.1":
version: 1.13.7
resolution: "underscore@npm:1.13.7"