mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-27 21:01:32 +08:00
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:
parent
ead0e22c60
commit
53dcda6942
103
packages/aiCore/examples/hub-provider-usage.ts
Normal file
103
packages/aiCore/examples/hub-provider-usage.ts
Normal 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 }
|
||||
@ -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'
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,136 +0,0 @@
|
||||
/**
|
||||
* 动态Provider注册表 - 完全基于AI SDK原生
|
||||
* 每次变更都重建registry,让AI 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: '>' })
|
||||
148
packages/aiCore/src/core/providers/HubProvider.ts
Normal file
148
packages/aiCore/src/core/providers/HubProvider.ts
Normal 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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
150
packages/aiCore/src/core/providers/RegistryManagement.ts
Normal file
150
packages/aiCore/src/core/providers/RegistryManagement.ts
Normal 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<':'>()
|
||||
@ -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
|
||||
}
|
||||
@ -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'
|
||||
|
||||
@ -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 }
|
||||
|
||||
@ -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 {
|
||||
// 已经是模型,直接返回
|
||||
|
||||
@ -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
|
||||
}))
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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)
|
||||
// }
|
||||
// }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user