feat(aiCore): introduce Hub Provider and enhance provider management

- Added a new example file demonstrating the usage of the Hub Provider for routing to multiple underlying providers.
- Implemented the Hub Provider to support model ID parsing and routing based on a specified format.
- Refactored provider management by introducing a Registry Management class for better organization and retrieval of provider instances.
- Updated the Provider Initializer to streamline the initialization and registration of providers, enhancing overall flexibility and usability.
- Removed outdated files related to provider creation and dynamic registration to simplify the codebase.
This commit is contained in:
lizhixuan 2025-08-26 00:31:41 +08:00
parent ead0e22c60
commit 53dcda6942
15 changed files with 788 additions and 803 deletions

View File

@ -0,0 +1,103 @@
/**
* Hub Provider 使
*
* 使Hub Provider功能来路由到多个底层provider
*/
import { createHubProvider, initializeProvider, providerRegistry } from '../src/index'
async function demonstrateHubProvider() {
try {
// 1. 初始化底层providers
console.log('📦 初始化底层providers...')
initializeProvider('openai', {
apiKey: process.env.OPENAI_API_KEY || 'sk-test-key'
})
initializeProvider('anthropic', {
apiKey: process.env.ANTHROPIC_API_KEY || 'sk-ant-test-key'
})
// 2. 创建Hub Provider自动包含所有已初始化的providers
console.log('🌐 创建Hub Provider...')
const aihubmixProvider = createHubProvider({
hubId: 'aihubmix',
debug: true
})
// 3. 注册Hub Provider
providerRegistry.registerProvider('aihubmix', aihubmixProvider)
console.log('✅ Hub Provider "aihubmix" 注册成功')
// 4. 使用Hub Provider访问不同的模型
console.log('\n🚀 使用Hub模型...')
// 通过Hub路由到OpenAI
const openaiModel = providerRegistry.languageModel('aihubmix:openai:gpt-4')
console.log('✓ OpenAI模型已获取:', openaiModel.modelId)
// 通过Hub路由到Anthropic
const anthropicModel = providerRegistry.languageModel('aihubmix:anthropic:claude-3.5-sonnet')
console.log('✓ Anthropic模型已获取:', anthropicModel.modelId)
// 5. 演示错误处理
console.log('\n❌ 演示错误处理...')
try {
// 尝试访问未初始化的provider
providerRegistry.languageModel('aihubmix:google:gemini-pro')
} catch (error) {
console.log('预期错误:', error.message)
}
try {
// 尝试使用错误的模型ID格式
providerRegistry.languageModel('aihubmix:invalid-format')
} catch (error) {
console.log('预期错误:', error.message)
}
// 6. 多个Hub Provider示例
console.log('\n🔄 创建多个Hub Provider...')
const localHubProvider = createHubProvider({
hubId: 'local-ai'
})
providerRegistry.registerProvider('local-ai', localHubProvider)
console.log('✅ Hub Provider "local-ai" 注册成功')
console.log('\n🎉 Hub Provider演示完成')
} catch (error) {
console.error('💥 演示过程中发生错误:', error)
}
}
// 演示简化的使用方式
function simplifiedUsageExample() {
console.log('\n📝 简化使用示例:')
console.log(`
// 1. 初始化providers
initializeProvider('openai', { apiKey: 'sk-xxx' })
initializeProvider('anthropic', { apiKey: 'sk-ant-xxx' })
// 2. 创建并注册Hub Provider
const hubProvider = createHubProvider({ hubId: 'aihubmix' })
providerRegistry.registerProvider('aihubmix', hubProvider)
// 3. 直接使用
const model1 = providerRegistry.languageModel('aihubmix:openai:gpt-4')
const model2 = providerRegistry.languageModel('aihubmix:anthropic:claude-3.5-sonnet')
`)
}
// 运行演示
if (require.main === module) {
demonstrateHubProvider()
simplifiedUsageExample()
}
export { demonstrateHubProvider, simplifiedUsageExample }

View File

@ -8,15 +8,8 @@ export type { NamedMiddleware } from './middleware'
export { createMiddlewares, wrapModelWithMiddlewares } from './middleware'
// 创建管理
export {
createBaseModel,
createImageModel,
createModel,
getProviderInfo,
getSupportedProviders,
ModelCreationError
} from './models'
export type { ModelConfig } from './models/types'
export { globalModelResolver, ModelResolver } from './models'
export type { ModelConfig as ModelConfigType } from './models/types'
// 执行管理
export type { ToolUseRequestContext } from './plugins/built-in/toolUsePlugin/type'

View File

@ -1,199 +0,0 @@
/**
* Model Creator
* Provider AI SDK Language Model Image Model
*/
import { ImageModelV2, type LanguageModelV2 } from '@ai-sdk/provider'
import { isOpenAIChatCompletionOnlyModel } from '../../utils/model'
import { createImageProvider, createProvider } from '../providers/creator'
import { aiProviderRegistry } from '../providers/registry'
import { type ProviderId, type ProviderSettingsMap } from '../providers/types'
// 错误类型
export class ModelCreationError extends Error {
constructor(
message: string,
public providerId?: string,
public cause?: Error
) {
super(message)
this.name = 'ModelCreationError'
}
}
/**
* AI SDK
* Provider 使 Provider 使 openai-compatible
*/
export async function createBaseModel<T extends ProviderId>({
providerId,
modelId,
providerSettings,
extraModelConfig
}: {
providerId: T
modelId: string
providerSettings: ProviderSettingsMap[T] & { mode?: 'chat' | 'responses' }
extraModelConfig?: any
}): Promise<LanguageModelV2>
export async function createBaseModel({
providerId,
modelId,
providerSettings,
extraModelConfig
}: {
providerId: string
modelId: string
providerSettings: ProviderSettingsMap['openai-compatible'] & { mode?: 'chat' | 'responses' }
extraModelConfig?: any
}): Promise<LanguageModelV2>
export async function createBaseModel({
providerId,
modelId,
providerSettings,
extraModelConfig
}: {
providerId: string
modelId: string
providerSettings: ProviderSettingsMap[ProviderId] & { mode?: 'chat' | 'responses' }
extraModelConfig?: any
}): Promise<LanguageModelV2> {
try {
// 获取Provider配置
const providerConfig = aiProviderRegistry.getProvider(providerId)
if (!providerConfig) {
throw new ModelCreationError(`Provider "${providerId}" is not registered`, providerId)
}
// 创建 provider 实例
const provider = await createProvider(providerConfig, providerSettings)
// 根据 provider 类型处理特殊逻辑
const finalProvider = handleProviderSpecificLogic(provider, providerConfig.id, providerSettings, modelId)
// 创建模型实例
if (typeof finalProvider === 'function') {
const model: LanguageModelV2 = finalProvider(modelId, extraModelConfig)
return model
} else {
throw new ModelCreationError(`Unknown model access pattern for provider "${providerId}"`)
}
} catch (error) {
if (error instanceof ModelCreationError) {
throw error
}
throw new ModelCreationError(
`Failed to create base model for provider "${providerId}": ${error instanceof Error ? error.message : 'Unknown error'}`,
providerId,
error instanceof Error ? error : undefined
)
}
}
/**
* Provider
*/
function handleProviderSpecificLogic(provider: any, providerId: string, providerSettings: any, modelId: string): any {
// OpenAI 特殊处理
if (providerId === 'openai') {
if (
'mode' in providerSettings &&
providerSettings.mode === 'responses' &&
!isOpenAIChatCompletionOnlyModel(modelId)
) {
return provider.responses
} else {
return provider.chat
}
}
// 其他 provider 直接返回
return provider
}
/**
*
*/
export async function createImageModel<T extends ProviderId>(
providerId: T,
modelId: string,
options: ProviderSettingsMap[T]
): Promise<ImageModelV2>
export async function createImageModel(
providerId: string,
modelId: string,
options: ProviderSettingsMap['openai-compatible']
): Promise<ImageModelV2>
export async function createImageModel(
providerId: string,
modelId: string = 'default',
options: any
): Promise<ImageModelV2> {
try {
if (!aiProviderRegistry.isSupported(providerId)) {
throw new ModelCreationError(`Provider "${providerId}" is not supported`, providerId)
}
const providerConfig = aiProviderRegistry.getProvider(providerId)
if (!providerConfig) {
throw new ModelCreationError(`Provider "${providerId}" is not registered`, providerId)
}
if (!providerConfig.supportsImageGeneration) {
throw new ModelCreationError(`Provider "${providerId}" does not support image generation`, providerId)
}
// 创建图像 provider 实例
const provider = await createImageProvider(providerConfig, options)
if (provider && typeof provider.image === 'function') {
return provider.image(modelId)
} else {
throw new ModelCreationError(`Image model function not found for provider "${providerId}"`)
}
} catch (error) {
if (error instanceof ModelCreationError) {
throw error
}
throw new ModelCreationError(
`Failed to create image model for provider "${providerId}": ${error instanceof Error ? error.message : 'Unknown error'}`,
providerId,
error instanceof Error ? error : undefined
)
}
}
/**
* Providers
*/
export function getSupportedProviders(): Array<{
id: string
name: string
}> {
return aiProviderRegistry.getAllProviders().map((provider) => ({
id: provider.id,
name: provider.name
}))
}
/**
* Provider
*/
export function getProviderInfo(providerId: string): {
id: string
name: string
isSupported: boolean
effectiveProvider: string
} {
const effectiveProviderId = aiProviderRegistry.isSupported(providerId) ? providerId : 'openai-compatible'
const provider = aiProviderRegistry.getProvider(effectiveProviderId)
return {
id: providerId,
name: provider?.name || providerId,
isSupported: aiProviderRegistry.isSupported(providerId),
effectiveProvider: effectiveProviderId
}
}

View File

@ -2,11 +2,14 @@
* - models模块的核心
* modelId解析为AI SDK的LanguageModel实例
*
* ModelCreator
*/
import { EmbeddingModelV2, ImageModelV2, LanguageModelV2 } from '@ai-sdk/provider'
import { EmbeddingModelV2, ImageModelV2, LanguageModelV2, LanguageModelV2Middleware } from '@ai-sdk/provider'
import { globalDynamicRegistry } from '../providers/DynamicProviderRegistry'
import { isOpenAIChatCompletionOnlyModel } from '../../utils/model'
import { wrapModelWithMiddlewares } from '../middleware/wrapper'
import { globalRegistryManagement } from '../providers/RegistryManagement'
export class ModelResolver {
/**
@ -14,31 +17,48 @@ export class ModelResolver {
*
* @param modelId ID 'gpt-4' 'anthropic>claude-3'
* @param fallbackProviderId modelId为传统格式时使用的providerId
* @param providerOptions provider配置选项使
* @param providerOptions provider配置选项OpenAI模式选择等
* @param middlewares
*/
async resolveLanguageModel(
modelId: string,
fallbackProviderId: string,
_providerOptions?: any
providerOptions?: any,
middlewares?: LanguageModelV2Middleware[]
): Promise<LanguageModelV2> {
// 检查是否是命名空间格式 (aihubmix>anthropic>claude-3)
if (modelId.includes('>')) {
return this.resolveNamespacedModel(modelId)
let finalProviderId = fallbackProviderId
let model: LanguageModelV2
// 🎯 处理 OpenAI 模式选择逻辑 (从 ModelCreator 迁移)
if (fallbackProviderId === 'openai' && providerOptions?.mode === 'chat') {
// 检查是否支持 chat 模式且不是只支持 chat 的模型
if (!isOpenAIChatCompletionOnlyModel(modelId)) {
finalProviderId = 'openai-chat'
}
// 否则使用默认的 openai (responses 模式)
}
// 传统格式使用fallbackProviderId + modelId (openai + gpt-4)
return this.resolveTraditionalModel(fallbackProviderId, modelId)
// 检查是否是命名空间格式
if (modelId.includes(':')) {
model = this.resolveNamespacedModel(modelId)
} else {
// 传统格式:使用处理后的 providerId + modelId
model = this.resolveTraditionalModel(finalProviderId, modelId)
}
// 🎯 应用中间件(如果有)
if (middlewares && middlewares.length > 0) {
model = wrapModelWithMiddlewares(model, middlewares)
}
return model
}
/**
*
*/
async resolveTextEmbeddingModel(
modelId: string,
fallbackProviderId: string,
_providerOptions?: any
): Promise<EmbeddingModelV2<string>> {
if (modelId.includes('>')) {
async resolveTextEmbeddingModel(modelId: string, fallbackProviderId: string): Promise<EmbeddingModelV2<string>> {
if (modelId.includes(':')) {
return this.resolveNamespacedEmbeddingModel(modelId)
}
@ -48,8 +68,8 @@ export class ModelResolver {
/**
*
*/
async resolveImageModel(modelId: string, fallbackProviderId: string, _providerOptions?: any): Promise<ImageModelV2> {
if (modelId.includes('>')) {
async resolveImageModel(modelId: string, fallbackProviderId: string): Promise<ImageModelV2> {
if (modelId.includes(':')) {
return this.resolveNamespacedImageModel(modelId)
}
@ -58,49 +78,49 @@ export class ModelResolver {
/**
*
* aihubmix>anthropic>claude-3 -> globalDynamicRegistry.languageModel('aihubmix>anthropic>claude-3')
* aihubmix:anthropic:claude-3 -> globalRegistryManagement.languageModel('aihubmix:anthropic:claude-3')
*/
private resolveNamespacedModel(modelId: string): LanguageModelV2 {
return globalDynamicRegistry.languageModel(modelId)
return globalRegistryManagement.languageModel(modelId as any)
}
/**
*
* providerId: 'openai', modelId: 'gpt-4' -> globalDynamicRegistry.languageModel('openai>gpt-4')
* providerId: 'openai', modelId: 'gpt-4' -> globalRegistryManagement.languageModel('openai:gpt-4')
*/
private resolveTraditionalModel(providerId: string, modelId: string): LanguageModelV2 {
const fullModelId = `${providerId}>${modelId}`
return globalDynamicRegistry.languageModel(fullModelId)
const fullModelId = `${providerId}:${modelId}`
return globalRegistryManagement.languageModel(fullModelId as any)
}
/**
*
*/
private resolveNamespacedEmbeddingModel(modelId: string): EmbeddingModelV2<string> {
return globalDynamicRegistry.textEmbeddingModel(modelId)
return globalRegistryManagement.textEmbeddingModel(modelId as any)
}
/**
*
*/
private resolveTraditionalEmbeddingModel(providerId: string, modelId: string): EmbeddingModelV2<string> {
const fullModelId = `${providerId}>${modelId}`
return globalDynamicRegistry.textEmbeddingModel(fullModelId)
const fullModelId = `${providerId}:${modelId}`
return globalRegistryManagement.textEmbeddingModel(fullModelId as any)
}
/**
*
*/
private resolveNamespacedImageModel(modelId: string): ImageModelV2 {
return globalDynamicRegistry.imageModel(modelId)
return globalRegistryManagement.imageModel(modelId as any)
}
/**
*
*/
private resolveTraditionalImageModel(providerId: string, modelId: string): ImageModelV2 {
const fullModelId = `${providerId}>${modelId}`
return globalDynamicRegistry.imageModel(fullModelId)
const fullModelId = `${providerId}:${modelId}`
return globalRegistryManagement.imageModel(fullModelId as any)
}
}

View File

@ -1,136 +0,0 @@
/**
* Provider注册表 - AI SDK原生
* registryAI SDK处理所有逻辑
*/
import { EmbeddingModelV2, ImageModelV2, LanguageModelV2, ProviderV2 } from '@ai-sdk/provider'
import { createProviderRegistry } from 'ai'
export class DynamicProviderRegistry {
private providers: Record<string, ProviderV2> = {}
private separator: string
private registry: any | null = null
constructor(options: { separator?: string } = {}) {
this.separator = options.separator || '>'
}
/**
* provider - registry
*/
registerProvider(id: string, provider: ProviderV2): this {
this.providers[id] = provider
this.rebuildRegistry()
return this
}
/**
* providers
*/
registerProviders(providers: Record<string, ProviderV2>): this {
Object.assign(this.providers, providers)
this.rebuildRegistry()
return this
}
/**
* provider
*/
unregisterProvider(id: string): this {
delete this.providers[id]
this.rebuildRegistry()
return this
}
/**
* registry -
*/
private rebuildRegistry(): void {
if (Object.keys(this.providers).length === 0) {
this.registry = null
return
}
this.registry = createProviderRegistry(this.providers, {
separator: this.separator
})
}
/**
* - AI SDK原生方法
*/
languageModel(id: string): LanguageModelV2 {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.languageModel(id)
}
/**
* - AI SDK原生方法
*/
textEmbeddingModel(id: string): EmbeddingModelV2<string> {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.textEmbeddingModel(id)
}
/**
* - AI SDK原生方法
*/
imageModel(id: string): ImageModelV2 {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.imageModel(id)
}
/**
* - AI SDK原生方法
*/
transcriptionModel(id: string): any {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.transcriptionModel(id)
}
/**
* - AI SDK原生方法
*/
speechModel(id: string): any {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.speechModel(id)
}
/**
* provider列表
*/
getRegisteredProviders(): string[] {
return Object.keys(this.providers)
}
/**
* providers
*/
hasProviders(): boolean {
return Object.keys(this.providers).length > 0
}
/**
* providers
*/
clear(): this {
this.providers = {}
this.registry = null
return this
}
}
/**
* registry实例
*/
export const globalDynamicRegistry = new DynamicProviderRegistry({ separator: '>' })

View File

@ -0,0 +1,148 @@
/**
* Hub Provider - provider
*
* 支持格式: hubId:providerId:modelId
* 例如: aihubmix:anthropic:claude-3.5-sonnet
*/
import { ProviderV2 } from '@ai-sdk/provider'
import { customProvider } from 'ai'
import { globalRegistryManagement } from './RegistryManagement'
export interface HubProviderConfig {
/** Hub的唯一标识符 */
hubId: string
/** 是否启用调试日志 */
debug?: boolean
}
export class HubProviderError extends Error {
constructor(
message: string,
public readonly hubId: string,
public readonly providerId?: string,
public readonly originalError?: Error
) {
super(message)
this.name = 'HubProviderError'
}
}
/**
* Hub模型ID
*/
function parseHubModelId(modelId: string): { provider: string; actualModelId: string } {
const parts = modelId.split(':')
if (parts.length !== 2) {
throw new HubProviderError(`Invalid hub model ID format. Expected "provider:modelId", got: ${modelId}`, 'unknown')
}
return {
provider: parts[0],
actualModelId: parts[1]
}
}
/**
* Hub Provider
*/
export function createHubProvider(config: HubProviderConfig): ProviderV2 {
const { hubId, debug = false } = config
function logDebug(message: string, ...args: any[]) {
if (debug) {
console.log(`[HubProvider:${hubId}] ${message}`, ...args)
}
}
function getTargetProvider(providerId: string): ProviderV2 {
// 从全局注册表获取provider实例
try {
const provider = (globalRegistryManagement as any).getProvider(providerId)
if (!provider) {
throw new HubProviderError(
`Provider "${providerId}" is not initialized. Please call initializeProvider("${providerId}", options) first.`,
hubId,
providerId
)
}
return provider
} catch (error) {
throw new HubProviderError(
`Failed to get provider "${providerId}": ${error instanceof Error ? error.message : 'Unknown error'}`,
hubId,
providerId,
error instanceof Error ? error : undefined
)
}
}
return customProvider({
fallbackProvider: {
languageModel: (modelId: string) => {
logDebug('Resolving language model:', modelId)
const { provider, actualModelId } = parseHubModelId(modelId)
const targetProvider = getTargetProvider(provider)
if (!targetProvider.languageModel) {
throw new HubProviderError(`Provider "${provider}" does not support language models`, hubId, provider)
}
return targetProvider.languageModel(actualModelId)
},
textEmbeddingModel: (modelId: string) => {
logDebug('Resolving text embedding model:', modelId)
const { provider, actualModelId } = parseHubModelId(modelId)
const targetProvider = getTargetProvider(provider)
if (!targetProvider.textEmbeddingModel) {
throw new HubProviderError(`Provider "${provider}" does not support text embedding models`, hubId, provider)
}
return targetProvider.textEmbeddingModel(actualModelId)
},
imageModel: (modelId: string) => {
logDebug('Resolving image model:', modelId)
const { provider, actualModelId } = parseHubModelId(modelId)
const targetProvider = getTargetProvider(provider)
if (!targetProvider.imageModel) {
throw new HubProviderError(`Provider "${provider}" does not support image models`, hubId, provider)
}
return targetProvider.imageModel(actualModelId)
},
transcriptionModel: (modelId: string) => {
logDebug('Resolving transcription model:', modelId)
const { provider, actualModelId } = parseHubModelId(modelId)
const targetProvider = getTargetProvider(provider)
if (!targetProvider.transcriptionModel) {
throw new HubProviderError(`Provider "${provider}" does not support transcription models`, hubId, provider)
}
return targetProvider.transcriptionModel(actualModelId)
},
speechModel: (modelId: string) => {
logDebug('Resolving speech model:', modelId)
const { provider, actualModelId } = parseHubModelId(modelId)
const targetProvider = getTargetProvider(provider)
if (!targetProvider.speechModel) {
throw new HubProviderError(`Provider "${provider}" does not support speech models`, hubId, provider)
}
return targetProvider.speechModel(actualModelId)
}
}
})
}

View File

@ -0,0 +1,150 @@
/**
* Provider
* provider
* AI SDK createProviderRegistry
*/
import { EmbeddingModelV2, ImageModelV2, LanguageModelV2, ProviderV2 } from '@ai-sdk/provider'
import { createProviderRegistry, type ProviderRegistryProvider } from 'ai'
type PROVIDERS = Record<string, ProviderV2>
export const DEFAULT_SEPARATOR = ':'
// export type MODEL_ID = `${string}${typeof DEFAULT_SEPARATOR}${string}`
export class RegistryManagement<SEPARATOR extends string = typeof DEFAULT_SEPARATOR> {
private providers: PROVIDERS = {}
private separator: SEPARATOR
private registry: ProviderRegistryProvider<PROVIDERS, SEPARATOR> | null = null
constructor(options: { separator: SEPARATOR } = { separator: DEFAULT_SEPARATOR as SEPARATOR }) {
this.separator = options.separator
}
/**
* provider
*/
registerProvider(id: string, provider: ProviderV2): this {
this.providers[id] = provider
this.rebuildRegistry()
return this
}
/**
* provider实例
*/
getProvider(id: string): ProviderV2 | undefined {
return this.providers[id]
}
/**
* providers
*/
registerProviders(providers: Record<string, ProviderV2>): this {
Object.assign(this.providers, providers)
this.rebuildRegistry()
return this
}
/**
* provider
*/
unregisterProvider(id: string): this {
delete this.providers[id]
this.rebuildRegistry()
return this
}
/**
* registry -
*/
private rebuildRegistry(): void {
if (Object.keys(this.providers).length === 0) {
this.registry = null
return
}
this.registry = createProviderRegistry<PROVIDERS, SEPARATOR>(this.providers, {
separator: this.separator
})
}
/**
* - AI SDK
*/
languageModel(id: `${string}${SEPARATOR}${string}`): LanguageModelV2 {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.languageModel(id)
}
/**
* - AI SDK
*/
textEmbeddingModel(id: `${string}${SEPARATOR}${string}`): EmbeddingModelV2<string> {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.textEmbeddingModel(id)
}
/**
* - AI SDK
*/
imageModel(id: `${string}${SEPARATOR}${string}`): ImageModelV2 {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.imageModel(id)
}
/**
* - AI SDK
*/
transcriptionModel(id: `${string}${SEPARATOR}${string}`): any {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.transcriptionModel(id)
}
/**
* - AI SDK
*/
speechModel(id: `${string}${SEPARATOR}${string}`): any {
if (!this.registry) {
throw new Error('No providers registered')
}
return this.registry.speechModel(id)
}
/**
* provider
*/
getRegisteredProviders(): string[] {
return Object.keys(this.providers)
}
/**
* providers
*/
hasProviders(): boolean {
return Object.keys(this.providers).length > 0
}
/**
* providers
*/
clear(): this {
this.providers = {}
this.registry = null
return this
}
}
/**
*
*/
export const globalRegistryManagement = new RegistryManagement<':'>()

View File

@ -1,110 +0,0 @@
/**
* Provider Creator
* ProviderConfig provider
*/
import { type ProviderConfig } from './types'
// 错误类型
export class ProviderCreationError extends Error {
constructor(
message: string,
public providerId?: string,
public cause?: Error
) {
super(message)
this.name = 'ProviderCreationError'
}
}
/**
* Provider
* creator +
*/
export async function createProvider(config: ProviderConfig, options: any): Promise<any> {
try {
// 验证配置
if (!validateProviderConfig(config)) {
throw new ProviderCreationError(
'Invalid provider configuration: must provide either creator function or import configuration',
config.id
)
}
config.validateOptions?.(options)
// 方式一:直接使用 creator 函数
if (config.creator) {
return config.creator(options)
}
// 方式二:动态导入 + 函数名
if (config.import && config.creatorFunctionName) {
const module = (await config.import()) as Record<string, unknown>
const creatorFunction = module[config.creatorFunctionName]
if (typeof creatorFunction !== 'function') {
throw new ProviderCreationError(
`Creator function "${config.creatorFunctionName}" not found in the imported module`,
config.id
)
}
return creatorFunction(options)
}
throw new ProviderCreationError('Unexpected provider configuration state', config.id)
} catch (error) {
if (error instanceof ProviderCreationError) {
throw error
}
throw new ProviderCreationError(
`Failed to create provider "${config.id}": ${error instanceof Error ? error.message : 'Unknown error'}`,
config.id,
error instanceof Error ? error : undefined
)
}
}
/**
* Provider
*/
export async function createImageProvider(config: ProviderConfig, options: any): Promise<any> {
try {
if (!config.supportsImageGeneration) {
throw new ProviderCreationError(`Provider "${config.id}" does not support image generation`, config.id)
}
// 如果有专门的图像 creator
if (config.imageCreator) {
return config.imageCreator(options)
}
// 否则使用普通的 provider 创建流程
return await createProvider(config, options)
} catch (error) {
if (error instanceof ProviderCreationError) {
throw error
}
throw new ProviderCreationError(
`Failed to create image provider "${config.id}": ${error instanceof Error ? error.message : 'Unknown error'}`,
config.id,
error instanceof Error ? error : undefined
)
}
}
/**
* Provider
*/
export function validateProviderConfig(config: ProviderConfig): boolean {
if (!config.id || !config.name) {
return false
}
if (!config.creator && !(config.import && config.creatorFunctionName)) {
return false
}
return true
}

View File

@ -2,21 +2,45 @@
* Providers -
*/
// ==================== 新版动态Registry(推荐使用)====================
// ==================== 新版架构(推荐使用)====================
// 基于AI SDK原生的动态Provider注册表
export { DynamicProviderRegistry, globalDynamicRegistry } from './DynamicProviderRegistry'
// Provider 注册表管理器
export { globalRegistryManagement, RegistryManagement } from './RegistryManagement'
// Provider 初始化器(核心功能)
export {
clearAllProviders,
getImageModel,
getInitializedProviders,
getLanguageModel,
getProviderInfo,
getSupportedProviders,
getTextEmbeddingModel,
hasInitializedProviders,
// initializeImageProvider, // deprecated: 使用 initializeProvider 即可
initializeProvider,
initializeProviders,
isProviderInitialized,
isProviderSupported,
ProviderInitializationError,
ProviderInitializer,
providerRegistry,
reinitializeProvider
} from './registry'
// ==================== 保留的导出(兼容性)====================
// 基础Provider数据源
export { baseProviderIds, baseProviders } from './schemas'
// Hub Provider 功能
export { createHubProvider, type HubProviderConfig, HubProviderError } from './HubProvider'
// 类型定义(可能被其他模块使用)
export type { ProviderConfig, ProviderId, ProviderSettingsMap } from './types'
// Provider创建功能可能被其他地方使用
export { createImageProvider, createProvider, ProviderCreationError, validateProviderConfig } from './creator'
// Provider验证功能使用更好的Zod版本
export { validateProviderConfig } from './schemas'
// 验证功能(可能被其他地方使用)
export { validateProviderId } from './schemas'

View File

@ -1,211 +1,232 @@
/**
* AI Provider
* - 使 schemas
* -
* - Provider
* Provider
* providers
* ModelCreator
*/
import {
baseProviders,
type DynamicProviderRegistration,
type ProviderConfig,
type ProviderId,
validateDynamicProviderRegistration,
validateProviderId
} from './schemas'
import { customProvider } from 'ai'
export class AiProviderRegistry {
private static instance: AiProviderRegistry
private registry = new Map<string, ProviderConfig>()
// 动态注册扩展
private dynamicMappings = new Map<string, string>()
private dynamicProviders = new Set<string>()
import { isOpenAIChatCompletionOnlyModel } from '../../utils/model'
import { globalRegistryManagement } from './RegistryManagement'
import { baseProviders } from './schemas'
private constructor() {
this.initializeProviders()
}
public static getInstance(): AiProviderRegistry {
if (!AiProviderRegistry.instance) {
AiProviderRegistry.instance = new AiProviderRegistry()
}
return AiProviderRegistry.instance
}
/**
* Providers
* 使 schemas baseProviders
*/
private initializeProviders(): void {
baseProviders.forEach((config) => {
this.registry.set(config.id, config as ProviderConfig)
})
}
/**
* Providers
*/
public getAllProviders(): ProviderConfig[] {
return Array.from(this.registry.values())
}
/**
* ID Provider
*/
public getProvider(id: string): ProviderConfig | undefined {
return this.registry.get(id) || this.registry.get('openai-compatible')
}
/**
* Provider
*/
public isSupported(id: string): boolean {
// 首先检查是否在注册表中
if (this.registry.has(id)) {
return true
}
// 然后检查是否是有效的 provider ID可能是新的动态 provider
return validateProviderId(id)
}
/**
* Provider
*/
public registerProvider(config: ProviderConfig): void {
// 使用 schemas 的验证函数
if (!validateProviderId(config.id)) {
throw new Error(`Invalid provider ID: ${config.id}`)
}
// 验证:不能同时提供两种方式
if (config.creator && config.import) {
console.warn('Both creator and import provided, creator will take precedence')
}
this.registry.set(config.id, config)
}
/**
* Provider并支持映射关系
*/
public registerDynamicProvider(config: DynamicProviderRegistration): boolean {
try {
// 使用 schemas 的验证函数
const validatedConfig = validateDynamicProviderRegistration(config)
if (!validatedConfig) {
console.error('Invalid dynamic provider configuration')
return false
}
// 注册provider
this.registerProvider(validatedConfig)
// 记录为动态provider
this.dynamicProviders.add(validatedConfig.id)
// 添加映射关系(如果提供)
if (validatedConfig.mappings) {
Object.entries(validatedConfig.mappings).forEach(([key, value]) => {
this.dynamicMappings.set(key, value)
})
}
return true
} catch (error) {
console.error(`Failed to register provider ${config.id}:`, error)
return false
}
}
/**
* Providers
*/
public registerMultipleProviders(configs: DynamicProviderRegistration[]): number {
let successCount = 0
configs.forEach((config) => {
if (this.registerDynamicProvider(config)) {
successCount++
}
})
return successCount
}
/**
* Provider映射
*/
public getProviderMapping(providerId: string): string | undefined {
return this.dynamicMappings.get(providerId) || (this.dynamicProviders.has(providerId) ? providerId : undefined)
}
/**
* Provider
*/
public isDynamicProvider(providerId: string): boolean {
return this.dynamicProviders.has(providerId)
}
/**
* Provider映射
*/
public getAllDynamicMappings(): Record<string, string> {
return Object.fromEntries(this.dynamicMappings)
}
/**
* Providers
*/
public getDynamicProviders(): string[] {
return Array.from(this.dynamicProviders)
}
/**
* Provider IDs
*/
public getAllValidProviderIds(): string[] {
return [...Array.from(this.registry.keys()), ...this.dynamicProviders]
}
/**
* Provider ID
*/
public validateProviderId(id: string): boolean {
return validateProviderId(id)
}
/**
* -
*/
public cleanup(): void {
this.registry.clear()
this.dynamicProviders.clear()
this.dynamicMappings.clear()
// 重新初始化基础 providers
this.initializeProviders()
/**
* Provider
*/
class ProviderInitializationError extends Error {
constructor(
message: string,
public providerId?: string,
public cause?: Error
) {
super(message)
this.name = 'ProviderInitializationError'
}
}
// 导出单例实例
export const aiProviderRegistry = AiProviderRegistry.getInstance()
/**
* Provider
*/
export class ProviderInitializer {
/**
* provider
*/
static initializeProvider(providerId: string, options: any): void {
try {
// 1. 从 schemas 获取 provider 配置
const providerConfig = baseProviders.find((p) => p.id === providerId)
if (!providerConfig) {
throw new ProviderInitializationError(`Provider configuration for '${providerId}' not found`, providerId)
}
// 便捷函数
export const getProvider = (id: string) => aiProviderRegistry.getProvider(id)
export const getAllProviders = () => aiProviderRegistry.getAllProviders()
export const isProviderSupported = (id: string) => aiProviderRegistry.isSupported(id)
export const registerProvider = (config: ProviderConfig) => aiProviderRegistry.registerProvider(config)
export const validateProviderIdRegistry = (id: string) => aiProviderRegistry.validateProviderId(id)
export const getAllValidProviderIds = () => aiProviderRegistry.getAllValidProviderIds()
// 2. 使用 creator 函数创建已配置的 provider
const configuredProvider = providerConfig.creator(options)
// 动态注册相关便捷函数
export const registerDynamicProvider = (config: DynamicProviderRegistration) =>
aiProviderRegistry.registerDynamicProvider(config)
export const registerMultipleProviders = (configs: DynamicProviderRegistration[]) =>
aiProviderRegistry.registerMultipleProviders(configs)
export const getProviderMapping = (providerId: string) => aiProviderRegistry.getProviderMapping(providerId)
export const isDynamicProvider = (providerId: string) => aiProviderRegistry.isDynamicProvider(providerId)
export const getAllDynamicMappings = () => aiProviderRegistry.getAllDynamicMappings()
export const getDynamicProviders = () => aiProviderRegistry.getDynamicProviders()
export const cleanup = () => aiProviderRegistry.cleanup()
// 3. 处理特殊逻辑并注册到全局管理器
this.handleProviderSpecificLogic(configuredProvider, providerId)
} catch (error) {
if (error instanceof ProviderInitializationError) {
throw error
}
throw new ProviderInitializationError(
`Failed to initialize provider ${providerId}: ${error instanceof Error ? error.message : 'Unknown error'}`,
providerId,
error instanceof Error ? error : undefined
)
}
}
// 导出类型
export type { DynamicProviderRegistration, ProviderConfig, ProviderId }
/**
* providers
*/
static initializeProviders(providers: Record<string, any>): void {
Object.entries(providers).forEach(([providerId, options]) => {
try {
this.initializeProvider(providerId, options)
} catch (error) {
console.error(`Failed to initialize provider ${providerId}:`, error)
}
})
}
/**
* provider ( ModelCreator )
*/
private static handleProviderSpecificLogic(provider: any, providerId: string): void {
if (providerId === 'openai') {
// 🎯 OpenAI 默认注册 (responses 模式)
globalRegistryManagement.registerProvider('openai', provider)
// 🎯 使用 AI SDK 官方的 customProvider 创建 chat 模式变体
const openaiChatProvider = customProvider({
fallbackProvider: {
...provider,
// 覆盖 languageModel 方法指向 chat
languageModel: (modelId: string) => provider.chat(modelId)
}
})
globalRegistryManagement.registerProvider('openai-chat', openaiChatProvider)
} else {
// 其他 provider 直接注册
globalRegistryManagement.registerProvider(providerId, provider)
}
}
/**
* provider ( ModelCreator )
*
* @deprecated provider初始化使 initializeProvider()
* provider实例可以同时支持文本和图像功能
*
* TODO: 考虑在下个版本中删除此方法
*/
// static initializeImageProvider(providerId: string, options: any): void {
// try {
// const providerConfig = baseProviders.find((p) => p.id === providerId)
// if (!providerConfig) {
// throw new ProviderInitializationError(`Provider configuration for '${providerId}' not found`, providerId)
// }
// if (!providerConfig.supportsImageGeneration) {
// throw new ProviderInitializationError(`Provider "${providerId}" does not support image generation`, providerId)
// }
// const provider = providerConfig.creator(options)
// // 注册图像 provider (使用特殊前缀区分)
// globalRegistryManagement.registerProvider(`${providerId}-image`, provider as any)
// } catch (error) {
// if (error instanceof ProviderInitializationError) {
// throw error
// }
// throw new ProviderInitializationError(
// `Failed to initialize image provider ${providerId}: ${error instanceof Error ? error.message : 'Unknown error'}`,
// providerId,
// error instanceof Error ? error : undefined
// )
// }
// }
/**
* provider
*/
static isProviderInitialized(providerId: string): boolean {
return globalRegistryManagement.getRegisteredProviders().includes(providerId)
}
/**
* provider
*/
static reinitializeProvider(providerId: string, options: any): void {
this.initializeProvider(providerId, options) // 会覆盖已有的
}
/**
* providers
*/
static clearAllProviders(): void {
globalRegistryManagement.clear()
}
}
// ==================== 便捷函数导出 ====================
export const initializeProvider = ProviderInitializer.initializeProvider.bind(ProviderInitializer)
export const initializeProviders = ProviderInitializer.initializeProviders.bind(ProviderInitializer)
// export const initializeImageProvider = ProviderInitializer.initializeImageProvider.bind(ProviderInitializer) // deprecated: 使用 initializeProvider 即可
export const isProviderInitialized = ProviderInitializer.isProviderInitialized.bind(ProviderInitializer)
export const reinitializeProvider = ProviderInitializer.reinitializeProvider.bind(ProviderInitializer)
export const clearAllProviders = ProviderInitializer.clearAllProviders.bind(ProviderInitializer)
// ==================== 全局管理器导出 ====================
export { globalRegistryManagement as providerRegistry }
// ==================== 便捷访问方法 ====================
export const getLanguageModel = (id: string) => globalRegistryManagement.languageModel(id as any)
export const getTextEmbeddingModel = (id: string) => globalRegistryManagement.textEmbeddingModel(id as any)
export const getImageModel = (id: string) => globalRegistryManagement.imageModel(id as any)
// ==================== 工具函数 (从 ModelCreator 迁移) ====================
/**
* Providers ( ModelCreator )
*/
export function getSupportedProviders(): Array<{
id: string
name: string
}> {
return baseProviders.map((provider) => ({
id: provider.id,
name: provider.name
}))
}
/**
* Provider
*/
export function isProviderSupported(providerId: string): boolean {
return getProviderInfo(providerId).isSupported
}
/**
* Provider ( ModelCreator )
*/
export function getProviderInfo(providerId: string): {
id: string
name: string
isSupported: boolean
isInitialized: boolean
effectiveProvider: string
} {
const provider = baseProviders.find((p) => p.id === providerId)
const isInitialized = globalRegistryManagement.getRegisteredProviders().includes(providerId)
return {
id: providerId,
name: provider?.name || providerId,
isSupported: !!provider,
isInitialized,
effectiveProvider: isInitialized ? providerId : 'openai-compatible'
}
}
/**
* providers
*/
export function getInitializedProviders(): string[] {
return globalRegistryManagement.getRegisteredProviders()
}
/**
* providers
*/
export function hasInitializedProviders(): boolean {
return globalRegistryManagement.hasProviders()
}
// ==================== 导出错误类型和工具函数 ====================
export { isOpenAIChatCompletionOnlyModel, ProviderInitializationError }

View File

@ -14,9 +14,9 @@ import {
import { type ProviderId } from '../../types'
import { globalModelResolver } from '../models'
import { getProviderInfo } from '../models/ModelCreator'
import { type ModelConfig } from '../models/types'
import { type AiPlugin, type AiRequestContext, definePlugin } from '../plugins'
import { getProviderInfo } from '../providers/registry'
import { ImageGenerationError, ImageModelResolutionError } from './errors'
import { PluginEngine } from './pluginEngine'
import { type RuntimeConfig } from './types'
@ -43,10 +43,9 @@ export class RuntimeExecutor<T extends ProviderId = ProviderId> {
name: '_internal_resolveModel',
enforce: 'post',
resolveModel: async (modelId: string, context: AiRequestContext) => {
// 从 context 中读取由用户插件注入的 extraModelConfig
const extraModelConfig = context.extraModelConfig || {}
return await this.resolveModel(modelId, middlewares, extraModelConfig)
resolveModel: async (modelId: string) => {
// 注意extraModelConfig 暂时不支持,已在新架构中移除
return await this.resolveModel(modelId, middlewares)
}
})
}
@ -272,15 +271,15 @@ export class RuntimeExecutor<T extends ProviderId = ProviderId> {
*/
private async resolveModel(
modelOrId: LanguageModel,
middlewares?: LanguageModelV2Middleware[],
extraModelConfig?: Record<string, any>
middlewares?: LanguageModelV2Middleware[]
): Promise<LanguageModelV2> {
if (typeof modelOrId === 'string') {
// 字符串modelId使用新的ModelResolver解析
// 🎯 字符串modelId使用新的ModelResolver解析,传递完整参数
return await globalModelResolver.resolveLanguageModel(
modelOrId, // 支持 'gpt-4' 和 'aihubmix>anthropic>claude-3'
modelOrId, // 支持 'gpt-4' 和 'aihubmix:anthropic:claude-3.5-sonnet'
this.config.providerId, // fallback provider
this.config.providerSettings // provider options
this.config.providerSettings, // provider options
middlewares // 中间件数组
)
} else {
// 已经是模型,直接返回
@ -296,9 +295,8 @@ export class RuntimeExecutor<T extends ProviderId = ProviderId> {
if (typeof modelOrId === 'string') {
// 字符串modelId使用新的ModelResolver解析
return await globalModelResolver.resolveImageModel(
modelOrId, // 支持 'dall-e-3' 和 'aihubmix>openai>dall-e-3'
this.config.providerId, // fallback provider
this.config.providerSettings // provider options
modelOrId, // 支持 'dall-e-3' 和 'aihubmix:openai:dall-e-3'
this.config.providerId // fallback provider
)
} else {
// 已经是模型,直接返回

View File

@ -4,11 +4,7 @@
*/
// 导入内部使用的类和函数
import {
getProviderInfo as factoryGetProviderInfo,
getSupportedProviders as factoryGetSupportedProviders
} from './core/models'
import { aiProviderRegistry, isProviderSupported } from './core/providers/registry'
import { getSupportedProviders, isProviderSupported } from './core/providers/registry'
import type { ProviderId } from './core/providers/types'
import type { ProviderSettingsMap } from './core/providers/types'
import { createExecutor } from './core/runtime'
@ -24,7 +20,7 @@ export {
} from './core/runtime'
// ==================== 高级API ====================
export { createModel } from './core/models'
export { globalModelResolver as modelResolver } from './core/models'
// ==================== 插件系统 ====================
export type { AiPlugin, AiRequestContext, HookResult, PluginManagerConfig } from './core/plugins'
@ -33,14 +29,7 @@ export { createContext, definePlugin, PluginManager } from './core/plugins'
export { PluginEngine } from './core/runtime/pluginEngine'
// ==================== 低级 API ====================
export {
createBaseModel as createApiClient,
createImageModel,
getProviderInfo as getClientInfo,
getSupportedProviders,
ModelCreationError
} from './core/models'
export { aiProviderRegistry } from './core/providers/registry'
export { providerRegistry } from './core/providers/registry'
// ==================== 类型定义 ====================
export type { ProviderConfig } from './core/providers/types'
@ -123,33 +112,32 @@ export {
type TypedProviderOptions
} from './core/options'
// ==================== 工具函数 ====================
// ==================== Provider 初始化和管理 ====================
export {
getAllDynamicMappings,
getAllProviders,
getAllValidProviderIds,
getDynamicProviders,
getProvider,
getProviderMapping,
isDynamicProvider,
clearAllProviders,
getImageModel,
getInitializedProviders,
// 访问功能
getLanguageModel,
getProviderInfo,
getTextEmbeddingModel,
hasInitializedProviders,
// initializeImageProvider, // deprecated: 使用 initializeProvider 即可
// 初始化功能
initializeProvider,
initializeProviders,
isProviderInitialized,
isProviderSupported,
// 动态注册功能
registerDynamicProvider,
registerMultipleProviders,
registerProvider,
// Zod 验证相关
validateProviderIdRegistry
// 错误类型
ProviderInitializationError,
reinitializeProvider
} from './core/providers/registry'
// ==================== Zod Schema 和验证 ====================
export {
type BaseProviderId,
baseProviderIds,
type DynamicProviderId,
type DynamicProviderRegistration,
validateDynamicProviderRegistration,
validateProviderId
} from './core/providers'
export { baseProviderIds, validateProviderId } from './core/providers'
// ==================== Hub Provider ====================
export { createHubProvider, type HubProviderConfig, HubProviderError } from './core/providers/HubProvider'
// ==================== Provider 配置工厂 ====================
export {
@ -177,17 +165,11 @@ export const AiCore = {
// 获取支持的providers
getSupportedProviders() {
return factoryGetSupportedProviders()
return getSupportedProviders()
},
// 检查provider支持
isSupported(providerId: string) {
isSupported(providerId: ProviderId) {
return isProviderSupported(providerId)
},
// 获取客户端信息
getClientInfo(providerId: string) {
return factoryGetProviderInfo(providerId)
}
}
@ -210,42 +192,18 @@ export const createXAIExecutor = (options: ProviderSettingsMap['xai'], plugins?:
// ==================== 调试和开发工具 ====================
export const DevTools = {
// 列出所有注册的providers
// 列出所有支持的providers
listProviders() {
return aiProviderRegistry.getAllProviders().map((p) => ({
id: p.id,
name: p.name
}))
},
// 测试provider连接
async testProvider(providerId: ProviderId, options: ProviderSettingsMap[ProviderId]) {
try {
const executor = createExecutor(providerId, options)
const info = executor.getClientInfo()
return {
success: true,
providerId: info.id,
name: info.name,
isSupported: info.isSupported
}
} catch (error) {
return {
success: false,
providerId,
error: error instanceof Error ? error.message : 'Unknown error'
}
}
return getSupportedProviders()
},
// 获取provider详细信息
getProviderDetails() {
const providers = aiProviderRegistry.getAllProviders()
const supportedProviders = getSupportedProviders()
return {
supportedProviders: providers.length,
registeredProviders: providers.length,
providers: providers.map((p) => ({
supportedProviders: supportedProviders.length,
providers: supportedProviders.map((p) => ({
id: p.id,
name: p.name
}))

View File

@ -8,7 +8,7 @@
* 3.
*/
import { createExecutor, generateImage, StreamTextParams } from '@cherrystudio/ai-core'
import { createExecutor, generateImage, initializeProvider, StreamTextParams } from '@cherrystudio/ai-core'
import { loggerService } from '@logger'
import { isNotSupportedImageSizeModel } from '@renderer/config/models'
import { addSpan, endSpan } from '@renderer/services/SpanManagerService'
@ -36,6 +36,21 @@ export default class ModernAiProvider {
// 只保存配置不预先创建executor
this.config = providerToAiSdkConfig(this.actualProvider)
// 初始化 provider 到全局管理器
try {
initializeProvider(this.config.providerId, this.config.options)
logger.debug('Provider initialized successfully', {
providerId: this.config.providerId,
hasOptions: !!this.config.options
})
} catch (error) {
// 如果 provider 已经初始化过,可能会抛出错误,这里可以忽略
logger.debug('Provider initialization skipped (may already be initialized)', {
providerId: this.config.providerId,
error: error instanceof Error ? error.message : String(error)
})
}
}
public getActualProvider() {

View File

@ -1,10 +1,9 @@
import { AiCore, getProviderMapping, type ProviderId } from '@cherrystudio/ai-core'
import { AiCore, type ProviderId } from '@cherrystudio/ai-core'
import { Provider } from '@renderer/types'
import { initializeNewProviders } from './providerConfigs'
// TODO
// 初始化新的Provider注册系统
initializeNewProviders()
// initializeNewProviders()
// 静态Provider映射 - 核心providers
const STATIC_PROVIDER_MAPPING: Record<string, ProviderId> = {
@ -21,24 +20,24 @@ export function getAiSdkProviderId(provider: Provider): ProviderId | 'openai-com
if (staticProviderId) {
return staticProviderId
}
// TODO
// 2. 检查动态注册的provider映射使用aiCore的函数
const dynamicProviderId = getProviderMapping(provider.id)
if (dynamicProviderId) {
return dynamicProviderId as ProviderId
}
// const dynamicProviderId = getProviderMapping(provider.id)
// if (dynamicProviderId) {
// return dynamicProviderId as ProviderId
// }
// 3. 检查provider.type的静态映射
const staticProviderType = STATIC_PROVIDER_MAPPING[provider.type]
if (staticProviderType) {
return staticProviderType
}
// TODO
// 4. 检查provider.type的动态映射
const dynamicProviderType = getProviderMapping(provider.type)
if (dynamicProviderType) {
return dynamicProviderType as ProviderId
}
// const dynamicProviderType = getProviderMapping(provider.type)
// if (dynamicProviderType) {
// return dynamicProviderType as ProviderId
// }
// 5. 检查AiCore是否直接支持
if (AiCore.isSupported(provider.id)) {

View File

@ -1,4 +1,4 @@
import { type ProviderConfig, registerMultipleProviders } from '@cherrystudio/ai-core'
import { type ProviderConfig } from '@cherrystudio/ai-core'
import { loggerService } from '@logger'
const logger = loggerService.withContext('ProviderConfigs')
@ -43,18 +43,19 @@ export const NEW_PROVIDER_CONFIGS: (ProviderConfig & {
}
] as const
/**
* Providers
* 使aiCore的动态注册功能
*/
export async function initializeNewProviders(): Promise<void> {
try {
const successCount = registerMultipleProviders(NEW_PROVIDER_CONFIGS)
// TODO
// /**
// * 初始化新的Providers
// * 使用aiCore的动态注册功能
// */
// export async function initializeNewProviders(): Promise<void> {
// try {
// const successCount = registerMultipleProviders(NEW_PROVIDER_CONFIGS)
if (successCount < NEW_PROVIDER_CONFIGS.length) {
logger.warn('Some providers failed to register. Check previous error logs.')
}
} catch (error) {
logger.error('Failed to initialize new providers:', error as Error)
}
}
// if (successCount < NEW_PROVIDER_CONFIGS.length) {
// logger.warn('Some providers failed to register. Check previous error logs.')
// }
// } catch (error) {
// logger.error('Failed to initialize new providers:', error as Error)
// }
// }