feat: update AI Core client types and provider registry

- Refactored `ApiClientFactory` and `UniversalAiSdkClient` to use the new `ProviderOptions` type for improved type safety.
- Removed deprecated `AiCoreRequest` interface to streamline request handling.
- Updated the provider registry to include the OpenRouter provider while removing unused providers, enhancing clarity and maintainability.
- Added new dependencies and updated the pnpm-lock.yaml to reflect changes in provider versions.
This commit is contained in:
suyao 2025-06-17 20:05:31 +08:00
parent 7c1b7ee40f
commit 8910281b09
5 changed files with 110 additions and 59 deletions

View File

@ -69,8 +69,8 @@ importers:
specifier: ^1.2.16
version: 1.2.16(zod@3.25.67)
'@openrouter/ai-sdk-provider':
specifier: ^0.7.2
version: 0.7.2(ai@4.3.16(react@19.1.0)(zod@3.25.67))(zod@3.25.67)
specifier: ^0.1.0
version: 0.1.0(zod@3.25.67)
ai:
specifier: ^4.3.16
version: 4.3.16(react@19.1.0)(zod@3.25.67)
@ -83,6 +83,9 @@ importers:
qwen-ai-provider:
specifier: ^0.1.0
version: 0.1.0(zod@3.25.67)
zhipu-ai-provider:
specifier: ^0.1.1
version: 0.1.1(zod@3.25.67)
devDependencies:
tsdown:
specifier: ^0.12.8
@ -198,6 +201,24 @@ packages:
zod:
optional: true
'@ai-sdk/provider-utils@2.1.10':
resolution: {integrity: sha512-4GZ8GHjOFxePFzkl3q42AU0DQOtTQ5w09vmaWUf/pKFXJPizlnzKSUkF0f+VkapIUfDugyMqPMT1ge8XQzVI7Q==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.0.0
peerDependenciesMeta:
zod:
optional: true
'@ai-sdk/provider-utils@2.1.5':
resolution: {integrity: sha512-PcNR7E4ovZGV/J47gUqaFlvzorgca6uUfN5WzfXJSFWeOeLunN+oxRVwgUOwj0zbmO0yGQTHQD+FHVw8s3Rz8w==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.0.0
peerDependenciesMeta:
zod:
optional: true
'@ai-sdk/provider-utils@2.2.8':
resolution: {integrity: sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==}
engines: {node: '>=18'}
@ -208,6 +229,14 @@ packages:
resolution: {integrity: sha512-XMsNGJdGO+L0cxhhegtqZ8+T6nn4EoShS819OvCgI2kLbYTIvk0GWFGD0AXJmxkxs3DrpsJxKAFukFR7bvTkgQ==}
engines: {node: '>=18'}
'@ai-sdk/provider@1.0.6':
resolution: {integrity: sha512-hwj/gFNxpDgEfTaYzCYoslmw01IY9kWLKl/wf8xuPvHtQIzlfXWmmUwc8PnCwxyt8cKzIuV0dfUghCf68HQ0SA==}
engines: {node: '>=18'}
'@ai-sdk/provider@1.0.9':
resolution: {integrity: sha512-jie6ZJT2ZR0uVOVCDc9R2xCX5I/Dum/wEK28lx21PJx6ZnFAN9EzD2WsPhcDWfCgGx3OAZZ0GyM3CEobXpa9LA==}
engines: {node: '>=18'}
'@ai-sdk/provider@1.1.3':
resolution: {integrity: sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==}
engines: {node: '>=18'}
@ -314,12 +343,11 @@ packages:
'@napi-rs/wasm-runtime@0.2.11':
resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==}
'@openrouter/ai-sdk-provider@0.7.2':
resolution: {integrity: sha512-Fry2mV7uGGJRmP9JntTZRc8ElESIk7AJNTacLbF6Syoeb5k8d7HPGkcK9rTXDlqBb8HgU1hOKtz23HojesTmnw==}
'@openrouter/ai-sdk-provider@0.1.0':
resolution: {integrity: sha512-kETuMSFu31Z9ND1lEl8cmXy+csCZBopKEpe33Pxz/B6J/AYOlGxvmdPKWlMqwkvE1dISuPMh9IL97Q6dof2Liw==}
engines: {node: '>=18'}
peerDependencies:
ai: ^4.3.16
zod: ^3.25.34
zod: ^3.0.0
'@opentelemetry/api@1.9.0':
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
@ -539,6 +567,10 @@ packages:
resolution: {integrity: sha512-v0eOBUbiaFojBu2s2NPBfYUoRR9GjcDNvCXVaqEf5vVfpIAh9f8RCo4vXTP8c63QRKCFwoLpMpTdPwwhEKVgzA==}
engines: {node: '>=14.18'}
eventsource-parser@3.0.2:
resolution: {integrity: sha512-6RxOBZ/cYgd8usLwsEl+EC09Au/9BcmCKYF2/xbml6DNczf7nv0MQb+7BA2F+li6//I+28VNlQR37XfQtcAJuA==}
engines: {node: '>=18.0.0'}
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
@ -769,6 +801,12 @@ packages:
whatwg-url@5.0.0:
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
zhipu-ai-provider@0.1.1:
resolution: {integrity: sha512-cVwvvGtPiQqgsGdBzHCHC5oQ7z6slEQTbXJ5+42gQGX4N5uRUvYj+YYLp7Cr1HPQGF3zR2p8vNbT5etPHD4NbA==}
engines: {node: '>=18'}
peerDependencies:
zod: ^3.0.0
zod-to-json-schema@3.24.5:
resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==}
peerDependencies:
@ -898,6 +936,24 @@ snapshots:
optionalDependencies:
zod: 3.25.67
'@ai-sdk/provider-utils@2.1.10(zod@3.25.67)':
dependencies:
'@ai-sdk/provider': 1.0.9
eventsource-parser: 3.0.2
nanoid: 3.3.11
secure-json-parse: 2.7.0
optionalDependencies:
zod: 3.25.67
'@ai-sdk/provider-utils@2.1.5(zod@3.25.67)':
dependencies:
'@ai-sdk/provider': 1.0.6
eventsource-parser: 3.0.2
nanoid: 3.3.11
secure-json-parse: 2.7.0
optionalDependencies:
zod: 3.25.67
'@ai-sdk/provider-utils@2.2.8(zod@3.25.67)':
dependencies:
'@ai-sdk/provider': 1.1.3
@ -909,6 +965,14 @@ snapshots:
dependencies:
json-schema: 0.4.0
'@ai-sdk/provider@1.0.6':
dependencies:
json-schema: 0.4.0
'@ai-sdk/provider@1.0.9':
dependencies:
json-schema: 0.4.0
'@ai-sdk/provider@1.1.3':
dependencies:
json-schema: 0.4.0
@ -1035,11 +1099,10 @@ snapshots:
'@tybys/wasm-util': 0.9.0
optional: true
'@openrouter/ai-sdk-provider@0.7.2(ai@4.3.16(react@19.1.0)(zod@3.25.67))(zod@3.25.67)':
'@openrouter/ai-sdk-provider@0.1.0(zod@3.25.67)':
dependencies:
'@ai-sdk/provider': 1.1.3
'@ai-sdk/provider-utils': 2.2.8(zod@3.25.67)
ai: 4.3.16(react@19.1.0)(zod@3.25.67)
'@ai-sdk/provider': 1.0.6
'@ai-sdk/provider-utils': 2.1.5(zod@3.25.67)
zod: 3.25.67
'@opentelemetry/api@1.9.0': {}
@ -1213,6 +1276,8 @@ snapshots:
eventsource-parser@1.1.2: {}
eventsource-parser@3.0.2: {}
extend@3.0.2: {}
fdir@6.4.6(picomatch@4.0.2):
@ -1448,6 +1513,12 @@ snapshots:
tr46: 0.0.3
webidl-conversions: 3.0.1
zhipu-ai-provider@0.1.1(zod@3.25.67):
dependencies:
'@ai-sdk/provider': 1.0.9
'@ai-sdk/provider-utils': 2.1.10(zod@3.25.67)
zod: 3.25.67
zod-to-json-schema@3.24.5(zod@3.25.67):
dependencies:
zod: 3.25.67

View File

@ -6,6 +6,7 @@
import type { LanguageModelV1 } from 'ai'
import { aiProviderRegistry } from '../providers/registry'
import { ProviderOptions } from './types'
// 客户端配置接口
export interface ClientConfig {
@ -37,7 +38,7 @@ export class ApiClientFactory {
static async createClient(
providerId: string,
modelId: string = 'default',
options: any = {}
options: ProviderOptions
): Promise<LanguageModelV1> {
try {
// 验证provider是否支持

View File

@ -6,6 +6,7 @@
import { generateObject, generateText, streamObject, streamText } from 'ai'
import { ApiClientFactory } from './ApiClientFactory'
import { ProviderOptions } from './types'
/**
* AI SDK
@ -14,16 +15,19 @@ import { ApiClientFactory } from './ApiClientFactory'
export class UniversalAiSdkClient {
constructor(
private readonly providerId: string,
private readonly options: any = {}
private readonly options: ProviderOptions
) {}
/**
*
* 使 AI SDK streamText
*/
async streamText(modelId: string, params: Omit<Parameters<typeof streamText>[0], 'model'>) {
async streamText(
modelId: string,
params: Omit<Parameters<typeof streamText>[0], 'model'>
): Promise<ReturnType<typeof streamText>> {
const model = await ApiClientFactory.createClient(this.providerId, modelId, this.options)
return await streamText({
return streamText({
model,
...params
})
@ -33,9 +37,12 @@ export class UniversalAiSdkClient {
*
* 使 AI SDK generateText
*/
async generateText(modelId: string, params: Omit<Parameters<typeof generateText>[0], 'model'>) {
async generateText(
modelId: string,
params: Omit<Parameters<typeof generateText>[0], 'model'>
): Promise<ReturnType<typeof generateText>> {
const model = await ApiClientFactory.createClient(this.providerId, modelId, this.options)
return await generateText({
return generateText({
model,
...params
})
@ -45,7 +52,10 @@ export class UniversalAiSdkClient {
*
* 使 AI SDK generateObject
*/
async generateObject(modelId: string, params: Omit<Parameters<typeof generateObject>[0], 'model'>) {
async generateObject(
modelId: string,
params: Omit<Parameters<typeof generateObject>[0], 'model'>
): Promise<ReturnType<typeof generateObject>> {
const model = await ApiClientFactory.createClient(this.providerId, modelId, this.options)
return await generateObject({
model,
@ -57,9 +67,12 @@ export class UniversalAiSdkClient {
*
* 使 AI SDK streamObject
*/
async streamObject(modelId: string, params: Omit<Parameters<typeof streamObject>[0], 'model'>) {
async streamObject(
modelId: string,
params: Omit<Parameters<typeof streamObject>[0], 'model'>
): Promise<ReturnType<typeof streamObject>> {
const model = await ApiClientFactory.createClient(this.providerId, modelId, this.options)
return await streamObject({
return streamObject({
model,
...params
})

View File

@ -1,5 +1,3 @@
import { CoreMessage } from 'ai'
export type ProviderOptions = {
name: string
apiKey?: string
@ -7,17 +5,3 @@ export type ProviderOptions = {
apiVersion?: string
headers?: Record<string, string | unknown>
}
export interface AiCoreRequest {
modelId: string
messages: CoreMessage[]
tools?: Record<string, any>
maxTokens?: number
temperature?: number
topP?: number
frequencyPenalty?: number
presencePenalty?: number
maxRetries?: number
abortSignal?: AbortSignal
headers?: Record<string, string | undefined>
}

View File

@ -158,30 +158,6 @@ export class AiProviderRegistry {
name: 'Vercel',
import: () => import('@ai-sdk/vercel'),
creatorFunctionName: 'createVercel'
},
{
id: 'qwen',
name: 'Qwen',
import: () => import('qwen-ai-provider'),
creatorFunctionName: 'createQwen'
},
{
id: 'ollama',
name: 'Ollama',
import: () => import('ollama-ai-provider'),
creatorFunctionName: 'createOllama'
},
{
id: 'anthropic-vertex',
name: 'Anthropic Vertex',
import: () => import('anthropic-vertex-ai'),
creatorFunctionName: 'createAnthropicVertex'
},
{
id: 'openrouter',
name: 'OpenRouter',
import: () => import('@openrouter/ai-sdk-provider'),
creatorFunctionName: 'createOpenRouter'
}
]
@ -210,6 +186,12 @@ export class AiProviderRegistry {
name: 'Anthropic Vertex AI',
import: () => import('anthropic-vertex-ai'),
creatorFunctionName: 'createAnthropicVertex'
},
{
id: 'openrouter',
name: 'OpenRouter',
import: () => import('@openrouter/ai-sdk-provider'),
creatorFunctionName: 'createOpenRouter'
}
]