mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-26 03:31:24 +08:00
feat: introduce Cherry Studio AI Core package with unified AI provider interface
- Added a new package `@cherry-studio/ai-core` that provides a unified interface for various AI providers based on the Vercel AI SDK. - Implemented core components including `ApiClientFactory`, `UniversalAiSdkClient`, and a provider registry for dynamic imports. - Included TypeScript support and a lightweight design for improved developer experience. - Documented architecture and usage examples in `AI_SDK_ARCHITECTURE.md` and `README.md`. - Updated `package.json` to include dependencies for supported AI providers. This package aims to streamline the integration of multiple AI providers while ensuring type safety and modularity.
This commit is contained in:
parent
f48e7aadb8
commit
7187e63ce2
688
packages/aiCore/AI_SDK_ARCHITECTURE.md
Normal file
688
packages/aiCore/AI_SDK_ARCHITECTURE.md
Normal file
@ -0,0 +1,688 @@
|
||||
# Cherry Studio AI Core 基于 Vercel AI SDK 的技术架构
|
||||
|
||||
## 1. 架构设计理念
|
||||
|
||||
### 1.1 设计目标
|
||||
- **统一接口**:使用 Vercel AI SDK 统一不同 AI Provider 的接口差异
|
||||
- **动态导入**:通过动态导入实现按需加载,减少打包体积
|
||||
- **最小包装**:直接使用 AI SDK 的类型和接口,避免重复定义
|
||||
- **中间件增强**:扩大中间件的介入范围,覆盖请求的全生命周期(规划中)
|
||||
- **类型安全**:利用 TypeScript 和 AI SDK 的类型系统确保类型安全
|
||||
- **轻量级**:专注核心功能,保持包的轻量和高效
|
||||
- **包级独立**:作为独立包管理,便于复用和维护
|
||||
|
||||
### 1.2 核心优势
|
||||
- **标准化**:AI SDK 提供统一的模型接口,减少适配工作
|
||||
- **简化维护**:废弃复杂的 XxxApiClient,统一为工厂函数模式
|
||||
- **更好的开发体验**:完整的 TypeScript 支持和丰富的生态系统
|
||||
- **性能优化**:AI SDK 内置优化和最佳实践
|
||||
- **模块化设计**:独立包结构,支持跨项目复用
|
||||
- **可扩展中间件**:支持在请求全生命周期中插入自定义逻辑
|
||||
|
||||
## 2. 整体架构图
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "Cherry Studio 主应用"
|
||||
UI["用户界面"]
|
||||
Components["React 组件"]
|
||||
end
|
||||
|
||||
subgraph "packages/aiCore (AI Core 包)"
|
||||
ApiClientFactory["ApiClientFactory (工厂类)"]
|
||||
UniversalClient["UniversalAiSdkClient (统一客户端)"]
|
||||
ProviderRegistry["Provider 注册表"]
|
||||
MiddlewareChain["中间件链 (规划中)"]
|
||||
end
|
||||
|
||||
subgraph "动态导入层"
|
||||
DynamicImport["动态导入"]
|
||||
end
|
||||
|
||||
subgraph "Vercel AI SDK"
|
||||
AICore["ai (核心库)"]
|
||||
OpenAI["@ai-sdk/openai"]
|
||||
Anthropic["@ai-sdk/anthropic"]
|
||||
Google["@ai-sdk/google"]
|
||||
XAI["@ai-sdk/xai"]
|
||||
Others["其他 19+ Providers"]
|
||||
end
|
||||
|
||||
subgraph "中间件生态 (规划中)"
|
||||
PreRequest["请求预处理"]
|
||||
StreamTransform["流转换"]
|
||||
PostProcess["后处理"]
|
||||
ErrorHandle["错误处理"]
|
||||
Logging["日志记录"]
|
||||
Cache["缓存"]
|
||||
end
|
||||
|
||||
UI --> ApiClientFactory
|
||||
Components --> ApiClientFactory
|
||||
ApiClientFactory --> UniversalClient
|
||||
UniversalClient --> MiddlewareChain
|
||||
MiddlewareChain --> ProviderRegistry
|
||||
ProviderRegistry --> DynamicImport
|
||||
DynamicImport --> OpenAI
|
||||
DynamicImport --> Anthropic
|
||||
DynamicImport --> Google
|
||||
DynamicImport --> XAI
|
||||
DynamicImport --> Others
|
||||
|
||||
UniversalClient --> AICore
|
||||
AICore --> streamText
|
||||
AICore --> generateText
|
||||
|
||||
MiddlewareChain --> PreRequest
|
||||
MiddlewareChain --> StreamTransform
|
||||
MiddlewareChain --> PostProcess
|
||||
MiddlewareChain --> ErrorHandle
|
||||
MiddlewareChain --> Logging
|
||||
MiddlewareChain --> Cache
|
||||
```
|
||||
|
||||
## 3. 包结构设计
|
||||
|
||||
### 3.1 包级文件结构(当前简化版 + 规划)
|
||||
|
||||
```
|
||||
packages/aiCore/
|
||||
├── src/
|
||||
│ ├── providers/
|
||||
│ │ ├── registry.ts # Provider 注册表 ✅
|
||||
│ │ └── types.ts # 核心类型定义 ✅
|
||||
│ ├── clients/
|
||||
│ │ ├── UniversalAiSdkClient.ts # 统一AI SDK客户端 ✅
|
||||
│ │ └── ApiClientFactory.ts # 客户端工厂 ✅
|
||||
│ ├── middleware/ # 中间件系统 (规划中)
|
||||
│ │ ├── lifecycle/ # 生命周期中间件
|
||||
│ │ │ ├── PreRequestMiddleware.ts
|
||||
│ │ │ ├── PostResponseMiddleware.ts
|
||||
│ │ │ ├── ErrorHandlingMiddleware.ts
|
||||
│ │ │ └── CacheMiddleware.ts
|
||||
│ │ ├── core/ # 核心中间件
|
||||
│ │ │ ├── StreamProcessingMiddleware.ts
|
||||
│ │ │ ├── RequestValidationMiddleware.ts
|
||||
│ │ │ └── ResponseTransformMiddleware.ts
|
||||
│ │ ├── feat/ # 特性中间件
|
||||
│ │ │ ├── ThinkingMiddleware.ts
|
||||
│ │ │ ├── ToolCallMiddleware.ts
|
||||
│ │ │ └── WebSearchMiddleware.ts
|
||||
│ │ ├── builder.ts # 中间件构建器
|
||||
│ │ ├── composer.ts # 中间件组合器
|
||||
│ │ ├── register.ts # 中间件注册表
|
||||
│ │ └── types.ts # 中间件类型定义
|
||||
│ ├── services/ # 高级服务 (规划中)
|
||||
│ │ ├── AiCoreService.ts # 统一服务入口
|
||||
│ │ ├── CompletionsService.ts # 文本生成服务
|
||||
│ │ ├── EmbeddingService.ts # 嵌入服务
|
||||
│ │ └── ImageService.ts # 图像生成服务
|
||||
│ └── index.ts # 包主入口文件 ✅
|
||||
├── package.json # 包配置文件 ✅
|
||||
├── tsconfig.json # TypeScript 配置 ✅
|
||||
├── README.md # 包说明文档 ✅
|
||||
└── AI_SDK_ARCHITECTURE.md # 本文档 ✅
|
||||
```
|
||||
|
||||
**图例:**
|
||||
- ✅ 已实现
|
||||
- 规划中:设计完成,待实现
|
||||
|
||||
### 3.2 包配置 (package.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@cherry-studio/ai-core",
|
||||
"version": "1.0.0",
|
||||
"description": "Cherry Studio AI Core - 基于 Vercel AI SDK 的统一 AI Provider 接口",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"dependencies": {
|
||||
"ai": "^4.3.16"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@ai-sdk/openai": { "optional": true },
|
||||
"@ai-sdk/anthropic": { "optional": true },
|
||||
"@ai-sdk/google": { "optional": true },
|
||||
"@ai-sdk/xai": { "optional": true }
|
||||
},
|
||||
"keywords": [
|
||||
"ai", "sdk", "vercel-ai-sdk", "cherry-studio"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 核心组件详解
|
||||
|
||||
### 4.1 Provider 注册表 (`providers/registry.ts`)
|
||||
|
||||
统一管理所有 AI Provider 的注册和动态导入。
|
||||
|
||||
**主要功能:**
|
||||
- 动态导入 AI SDK providers
|
||||
- 提供统一的 Provider 创建接口
|
||||
- 支持 19+ 官方 AI SDK providers
|
||||
- 类型安全的 Provider 配置
|
||||
|
||||
**核心 API:**
|
||||
```typescript
|
||||
export interface ProviderConfig {
|
||||
id: string
|
||||
name: string
|
||||
import: () => Promise<any>
|
||||
creatorFunctionName: string
|
||||
}
|
||||
|
||||
export class AiProviderRegistry {
|
||||
getProvider(id: string): ProviderConfig | undefined
|
||||
getAllProviders(): ProviderConfig[]
|
||||
isSupported(id: string): boolean
|
||||
registerProvider(config: ProviderConfig): void
|
||||
}
|
||||
```
|
||||
|
||||
**支持的 Providers:**
|
||||
- OpenAI, Anthropic, Google, XAI
|
||||
- Azure OpenAI, Amazon Bedrock, Google Vertex
|
||||
- Groq, Together.ai, Fireworks, DeepSeek
|
||||
- Cerebras, DeepInfra, Replicate, Perplexity
|
||||
- Cohere, Fal AI, Vercel (19+ providers)
|
||||
|
||||
### 4.2 统一AI SDK客户端 (`clients/UniversalAiSdkClient.ts`)
|
||||
|
||||
将不同 AI providers 包装为统一接口。
|
||||
|
||||
**主要功能:**
|
||||
- 异步初始化和动态加载
|
||||
- 统一的 stream() 和 generate() 方法
|
||||
- 直接使用 AI SDK 的 streamText() 和 generateText()
|
||||
- 配置验证和错误处理
|
||||
|
||||
**核心 API:**
|
||||
```typescript
|
||||
export class UniversalAiSdkClient {
|
||||
async initialize(): Promise<void>
|
||||
isInitialized(): boolean
|
||||
async stream(request: any): Promise<any>
|
||||
async generate(request: any): Promise<any>
|
||||
validateConfig(): boolean
|
||||
getProviderInfo(): { id: string; name: string; isInitialized: boolean }
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 客户端工厂 (`clients/ApiClientFactory.ts`)
|
||||
|
||||
统一创建和管理 AI SDK 客户端。
|
||||
|
||||
**主要功能:**
|
||||
- 统一的客户端创建接口
|
||||
- 智能缓存和复用机制
|
||||
- 批量创建和健康检查
|
||||
- 错误处理和重试
|
||||
|
||||
**核心 API:**
|
||||
```typescript
|
||||
export class ApiClientFactory {
|
||||
static async createAiSdkClient(providerId: string, options: any): Promise<UniversalAiSdkClient>
|
||||
static getCachedClient(providerId: string, options: any): UniversalAiSdkClient | undefined
|
||||
static clearCache(): void
|
||||
static async healthCheck(): Promise<HealthCheckResult>
|
||||
static getSupportedProviders(): ProviderInfo[]
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 增强的中间件系统 (规划中)
|
||||
|
||||
扩展中间件架构,支持请求全生命周期的介入。
|
||||
|
||||
**生命周期阶段:**
|
||||
1. **Pre-Request**:请求预处理、参数验证、缓存检查
|
||||
2. **Request**:实际的 AI SDK 调用
|
||||
3. **Stream Processing**:流式响应处理、实时转换
|
||||
4. **Post-Response**:响应后处理、结果聚合
|
||||
5. **Error Handling**:错误处理、重试、降级
|
||||
|
||||
**中间件分类:**
|
||||
|
||||
**生命周期中间件:**
|
||||
- `PreRequestMiddleware`:请求前处理,参数验证、权限检查
|
||||
- `PostResponseMiddleware`:响应后处理,结果转换、统计记录
|
||||
- `ErrorHandlingMiddleware`:错误处理,重试机制、降级策略
|
||||
- `CacheMiddleware`:缓存中间件,请求缓存、结果缓存
|
||||
|
||||
**核心中间件:**
|
||||
- `StreamProcessingMiddleware`:流式处理,chunk 转换、进度追踪
|
||||
- `RequestValidationMiddleware`:请求验证,schema 验证、安全检查
|
||||
- `ResponseTransformMiddleware`:响应转换,格式标准化、类型转换
|
||||
|
||||
**特性中间件:**
|
||||
- `ThinkingMiddleware`:思考过程中间件,记录推理步骤
|
||||
- `ToolCallMiddleware`:工具调用中间件,函数调用处理
|
||||
- `WebSearchMiddleware`:网络搜索中间件,集成搜索功能
|
||||
|
||||
**中间件 API 设计:**
|
||||
```typescript
|
||||
export interface Middleware {
|
||||
name: string
|
||||
priority: number
|
||||
execute(context: MiddlewareContext, next: () => Promise<void>): Promise<void>
|
||||
}
|
||||
|
||||
export interface MiddlewareContext {
|
||||
request: AiCoreRequest
|
||||
response?: AiCoreResponse
|
||||
error?: Error
|
||||
metadata: Record<string, any>
|
||||
provider: string
|
||||
model: string
|
||||
}
|
||||
|
||||
export class MiddlewareChain {
|
||||
use(middleware: Middleware): this
|
||||
compose(): (context: MiddlewareContext) => Promise<void>
|
||||
execute(context: MiddlewareContext): Promise<void>
|
||||
}
|
||||
```
|
||||
|
||||
### 4.5 统一服务接口 (规划中)
|
||||
|
||||
作为包的主要对外接口,提供高级 AI 功能。
|
||||
|
||||
**服务方法:**
|
||||
- `completions()`: 文本生成
|
||||
- `streamCompletions()`: 流式文本生成
|
||||
- `generateObject()`: 结构化数据生成
|
||||
- `generateImage()`: 图像生成
|
||||
- `embed()`: 文本嵌入
|
||||
|
||||
**API 设计:**
|
||||
```typescript
|
||||
export class AiCoreService {
|
||||
constructor(middlewares?: Middleware[])
|
||||
|
||||
async completions(request: CompletionRequest): Promise<CompletionResponse>
|
||||
async streamCompletions(request: CompletionRequest): Promise<StreamCompletionResponse>
|
||||
async generateObject<T>(request: ObjectGenerationRequest): Promise<T>
|
||||
async generateImage(request: ImageGenerationRequest): Promise<ImageResponse>
|
||||
async embed(request: EmbeddingRequest): Promise<EmbeddingResponse>
|
||||
|
||||
use(middleware: Middleware): this
|
||||
configure(config: AiCoreConfig): this
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 使用方式
|
||||
|
||||
### 5.1 基础用法
|
||||
|
||||
```typescript
|
||||
import { createAiSdkClient } from '@cherry-studio/ai-core'
|
||||
|
||||
// 创建 OpenAI 客户端
|
||||
const client = await createAiSdkClient('openai', {
|
||||
apiKey: 'your-api-key'
|
||||
})
|
||||
|
||||
// 流式生成
|
||||
const result = await client.stream({
|
||||
modelId: 'gpt-4',
|
||||
messages: [{ role: 'user', content: 'Hello!' }]
|
||||
})
|
||||
|
||||
// 非流式生成
|
||||
const response = await client.generate({
|
||||
modelId: 'gpt-4',
|
||||
messages: [{ role: 'user', content: 'Hello!' }]
|
||||
})
|
||||
```
|
||||
|
||||
### 5.2 便捷函数
|
||||
|
||||
```typescript
|
||||
import { createOpenAIClient, streamGeneration } from '@cherry-studio/ai-core'
|
||||
|
||||
// 快速创建特定 provider 客户端
|
||||
const client = await createOpenAIClient({
|
||||
apiKey: 'your-api-key'
|
||||
})
|
||||
|
||||
// 便捷的一次性调用
|
||||
const result = await streamGeneration(
|
||||
'anthropic',
|
||||
'claude-3-sonnet',
|
||||
[{ role: 'user', content: 'Hello!' }],
|
||||
{ apiKey: 'your-api-key' }
|
||||
)
|
||||
```
|
||||
|
||||
### 5.3 多 Provider 支持
|
||||
|
||||
```typescript
|
||||
import { createAiSdkClient, AiCore } from '@cherry-studio/ai-core'
|
||||
|
||||
// 检查支持的 providers
|
||||
const providers = AiCore.getSupportedProviders()
|
||||
console.log(`支持 ${providers.length} 个 AI providers`)
|
||||
|
||||
// 创建多个 provider 客户端
|
||||
const openai = await createAiSdkClient('openai', { apiKey: 'openai-key' })
|
||||
const anthropic = await createAiSdkClient('anthropic', { apiKey: 'anthropic-key' })
|
||||
const google = await createAiSdkClient('google', { apiKey: 'google-key' })
|
||||
const xai = await createAiSdkClient('xai', { apiKey: 'xai-key' })
|
||||
```
|
||||
|
||||
### 5.4 在 Cherry Studio 中集成
|
||||
|
||||
```typescript
|
||||
// 替换现有的 XxxApiClient
|
||||
// 之前:
|
||||
// const openaiClient = new OpenAIApiClient(config)
|
||||
// const anthropicClient = new AnthropicApiClient(config)
|
||||
|
||||
// 现在:
|
||||
import { createAiSdkClient } from '@cherry-studio/ai-core'
|
||||
|
||||
const createProviderClient = async (provider: CherryProvider) => {
|
||||
return await createAiSdkClient(provider.id, {
|
||||
apiKey: provider.apiKey,
|
||||
baseURL: provider.baseURL
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### 5.5 中间件使用 (规划中)
|
||||
|
||||
```typescript
|
||||
import {
|
||||
AiCoreService,
|
||||
ThinkingMiddleware,
|
||||
CacheMiddleware,
|
||||
LoggingMiddleware
|
||||
} from '@cherry-studio/ai-core'
|
||||
|
||||
// 创建带中间件的服务
|
||||
const aiService = new AiCoreService()
|
||||
.use(new CacheMiddleware({ ttl: 3600 }))
|
||||
.use(new LoggingMiddleware({ level: 'info' }))
|
||||
.use(new ThinkingMiddleware({ recordSteps: true }))
|
||||
|
||||
// 使用增强的服务
|
||||
const result = await aiService.streamCompletions({
|
||||
provider: 'openai',
|
||||
model: 'gpt-4',
|
||||
messages: [{ role: 'user', content: 'Explain quantum computing' }],
|
||||
middleware: {
|
||||
thinking: { enabled: true },
|
||||
cache: { enabled: true, key: 'quantum-explanation' }
|
||||
}
|
||||
})
|
||||
|
||||
// 自定义中间件
|
||||
class CustomMiddleware implements Middleware {
|
||||
name = 'custom'
|
||||
priority = 100
|
||||
|
||||
async execute(context: MiddlewareContext, next: () => Promise<void>): Promise<void> {
|
||||
console.log('Before request:', context.request)
|
||||
|
||||
await next() // 执行下一个中间件或实际请求
|
||||
|
||||
console.log('After response:', context.response)
|
||||
}
|
||||
}
|
||||
|
||||
aiService.use(new CustomMiddleware())
|
||||
```
|
||||
|
||||
### 5.6 完整的工作流示例 (规划中)
|
||||
|
||||
```typescript
|
||||
import {
|
||||
createAiSdkClient,
|
||||
AiCoreService,
|
||||
MiddlewareChain,
|
||||
PreRequestMiddleware,
|
||||
StreamProcessingMiddleware,
|
||||
PostResponseMiddleware
|
||||
} from '@cherry-studio/ai-core'
|
||||
|
||||
// 创建完整的工作流
|
||||
const createEnhancedAiService = async () => {
|
||||
// 创建中间件链
|
||||
const middlewareChain = new MiddlewareChain()
|
||||
.use(new PreRequestMiddleware({
|
||||
validateApiKey: true,
|
||||
checkRateLimit: true
|
||||
}))
|
||||
.use(new StreamProcessingMiddleware({
|
||||
enableProgressTracking: true,
|
||||
chunkTransform: (chunk) => ({
|
||||
...chunk,
|
||||
timestamp: Date.now()
|
||||
})
|
||||
}))
|
||||
.use(new PostResponseMiddleware({
|
||||
saveToHistory: true,
|
||||
calculateMetrics: true
|
||||
}))
|
||||
|
||||
// 创建服务实例
|
||||
const service = new AiCoreService(middlewareChain.middlewares)
|
||||
|
||||
return service
|
||||
}
|
||||
|
||||
// 使用增强服务
|
||||
const enhancedService = await createEnhancedAiService()
|
||||
|
||||
const response = await enhancedService.completions({
|
||||
provider: 'anthropic',
|
||||
model: 'claude-3-sonnet',
|
||||
messages: [
|
||||
{ role: 'user', content: 'Write a technical blog post about AI middleware' }
|
||||
],
|
||||
options: {
|
||||
temperature: 0.7,
|
||||
maxTokens: 2000
|
||||
},
|
||||
middleware: {
|
||||
// 中间件特定配置
|
||||
thinking: { recordSteps: true },
|
||||
cache: { enabled: true, ttl: 1800 },
|
||||
logging: { level: 'debug' }
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 6. 与现有架构的对比
|
||||
|
||||
| 方面 | 现有架构 | 新架构 (AI Core 包) |
|
||||
|------|----------|-------------------|
|
||||
| **代码组织** | 集成在主应用中 | 独立包,模块化管理 |
|
||||
| **Provider 管理** | 各自独立的 XxxApiClient | 统一的 Provider 注册表 + 工厂 |
|
||||
| **接口标准化** | 手动适配各 Provider 差异 | AI SDK 统一接口 |
|
||||
| **类型安全** | 部分类型安全 | 完整的 TypeScript 支持 |
|
||||
| **维护成本** | 每个 Provider 需要单独维护 | 统一维护,新 Provider 快速接入 |
|
||||
| **包体积** | 所有 Provider 都打包 | 按需加载,动态导入 |
|
||||
| **复用性** | 仅限当前项目 | 可跨项目复用 |
|
||||
| **扩展性** | 添加新 Provider 复杂 | 只需在注册表中添加配置 |
|
||||
|
||||
## 7. 简化设计原则
|
||||
|
||||
### 7.1 最小包装原则
|
||||
- 直接使用 AI SDK 的类型,不重复定义
|
||||
- 避免过度抽象和复杂的中间层
|
||||
- 保持与 AI SDK 原生 API 的一致性
|
||||
|
||||
### 7.2 动态导入优化
|
||||
```typescript
|
||||
// 按需加载,减少打包体积
|
||||
const module = await import('@ai-sdk/openai')
|
||||
const createOpenAI = module.createOpenAI
|
||||
```
|
||||
|
||||
### 7.3 类型安全
|
||||
```typescript
|
||||
// 直接使用 AI SDK 类型
|
||||
import { streamText, generateText } from 'ai'
|
||||
|
||||
// 避免重复定义,直接传递参数
|
||||
return streamText({ model, ...request })
|
||||
```
|
||||
|
||||
### 7.4 配置简化
|
||||
```typescript
|
||||
// 简化的 Provider 配置
|
||||
interface ProviderConfig {
|
||||
id: string // provider 标识
|
||||
name: string // 显示名称
|
||||
import: () => Promise<any> // 动态导入函数
|
||||
creatorFunctionName: string // 创建函数名
|
||||
}
|
||||
```
|
||||
|
||||
## 8. 技术要点
|
||||
|
||||
### 8.1 动态导入策略
|
||||
- **按需加载**:只加载用户实际使用的 providers
|
||||
- **缓存机制**:避免重复导入和初始化
|
||||
- **错误处理**:优雅处理导入失败的情况
|
||||
|
||||
### 8.2 依赖管理策略
|
||||
- **核心依赖**:`ai` 库作为必需依赖
|
||||
- **可选依赖**:所有 `@ai-sdk/*` 包都是可选的
|
||||
- **版本兼容**:支持 AI SDK v3-v5 版本
|
||||
|
||||
### 8.3 缓存策略
|
||||
- **客户端缓存**:基于 provider + options 的智能缓存
|
||||
- **配置哈希**:安全的 API key 哈希处理
|
||||
- **生命周期管理**:支持缓存清理和验证
|
||||
|
||||
## 9. 迁移策略
|
||||
|
||||
### 9.1 阶段一:包基础搭建 (Week 1) ✅ 已完成
|
||||
1. ✅ 创建简化的包结构
|
||||
2. ✅ 实现 Provider 注册表
|
||||
3. ✅ 创建统一客户端和工厂
|
||||
4. ✅ 配置构建和类型系统
|
||||
|
||||
### 9.2 阶段二:核心功能完善 (Week 2) ✅ 已完成
|
||||
1. ✅ 支持 19+ 官方 AI SDK providers
|
||||
2. ✅ 实现缓存和错误处理
|
||||
3. ✅ 完善类型安全和 API 设计
|
||||
4. ✅ 添加便捷函数和工具
|
||||
|
||||
### 9.3 阶段三:集成测试 (Week 3) 🔄 进行中
|
||||
1. 在 Cherry Studio 中集成测试
|
||||
2. 功能完整性验证
|
||||
3. 性能基准测试
|
||||
4. 兼容性问题修复
|
||||
|
||||
### 9.4 阶段四:中间件系统实现 (Week 4-5) 📋 规划中
|
||||
1. **中间件核心架构**
|
||||
- 实现 `MiddlewareChain` 和 `MiddlewareContext`
|
||||
- 创建中间件接口和基础类型
|
||||
- 建立中间件生命周期管理
|
||||
|
||||
2. **生命周期中间件**
|
||||
- `PreRequestMiddleware`:请求预处理
|
||||
- `PostResponseMiddleware`:响应后处理
|
||||
- `ErrorHandlingMiddleware`:错误处理
|
||||
- `CacheMiddleware`:缓存机制
|
||||
|
||||
3. **核心中间件**
|
||||
- `StreamProcessingMiddleware`:流式处理
|
||||
- `RequestValidationMiddleware`:请求验证
|
||||
- `ResponseTransformMiddleware`:响应转换
|
||||
|
||||
4. **集成到现有架构**
|
||||
- 在 `UniversalAiSdkClient` 中集成中间件链
|
||||
- 更新 `ApiClientFactory` 支持中间件配置
|
||||
- 创建 `AiCoreService` 统一服务接口
|
||||
|
||||
### 9.5 阶段五:特性中间件 (Week 6) 📋 规划中
|
||||
1. **Cherry Studio 特性中间件**
|
||||
- `ThinkingMiddleware`:思考过程记录
|
||||
- `ToolCallMiddleware`:工具调用处理
|
||||
- `WebSearchMiddleware`:网络搜索集成
|
||||
|
||||
2. **高级功能**
|
||||
- 中间件组合器和构建器
|
||||
- 动态中间件加载
|
||||
- 中间件配置管理
|
||||
|
||||
### 9.6 阶段六:文档和发布 (Week 7) 📋 规划中
|
||||
1. 完善使用文档和示例
|
||||
2. 中间件开发指南
|
||||
3. 准备发布到 npm
|
||||
4. 建立维护流程
|
||||
|
||||
### 9.7 阶段七:生态系统扩展 (Week 8+) 🚀 未来规划
|
||||
1. 社区中间件插件系统
|
||||
2. 可视化中间件编排工具
|
||||
3. 性能监控和分析
|
||||
4. 高级缓存策略
|
||||
|
||||
## 10. 预期收益
|
||||
|
||||
### 10.1 开发效率提升
|
||||
- **90%** 减少新 Provider 接入时间(只需添加注册表配置)
|
||||
- **70%** 减少维护工作量
|
||||
- **95%** 提升开发体验(统一接口 + 类型安全)
|
||||
- **独立开发**:可以独立于主应用开发和测试
|
||||
|
||||
### 10.2 代码质量改善
|
||||
- 完整的 TypeScript 类型安全
|
||||
- 统一的错误处理机制
|
||||
- 标准化的 AI SDK 接口
|
||||
- 更好的测试覆盖率
|
||||
|
||||
### 10.3 架构优势
|
||||
- **轻量级**:最小化的包装层
|
||||
- **可复用**:其他项目可以直接使用
|
||||
- **可维护**:独立版本管理和发布
|
||||
- **可扩展**:新 provider 只需配置即可
|
||||
|
||||
### 10.4 生态系统价值
|
||||
- 支持 AI SDK 的完整生态系统
|
||||
- 可以独立发布到 npm
|
||||
- 为开源社区贡献价值
|
||||
- 建立统一的 AI 基础设施
|
||||
|
||||
## 11. 风险评估与应对
|
||||
|
||||
### 11.1 技术风险
|
||||
- **AI SDK 版本兼容**:支持多版本兼容策略
|
||||
- **依赖管理**:合理使用 peerDependencies
|
||||
- **类型一致性**:直接使用 AI SDK 类型
|
||||
- **性能影响**:最小化包装层开销
|
||||
|
||||
### 11.2 迁移风险
|
||||
- **功能对等性**:确保所有现有功能都能实现
|
||||
- **API 兼容性**:提供平滑的迁移路径
|
||||
- **集成复杂度**:保持简单的集成方式
|
||||
- **学习成本**:提供清晰的使用文档
|
||||
|
||||
## 12. 总结
|
||||
|
||||
简化的 AI Core 架构专注于核心价值:
|
||||
|
||||
### 12.1 核心价值
|
||||
- **统一接口**:一套 API 支持 19+ AI providers
|
||||
- **按需加载**:只打包用户实际使用的 providers
|
||||
- **类型安全**:完整的 TypeScript 支持
|
||||
- **轻量高效**:最小化的包装层
|
||||
|
||||
### 12.2 设计哲学
|
||||
- **直接使用 AI SDK**:避免重复造轮子
|
||||
- **最小包装**:只在必要时添加抽象层
|
||||
- **开发者友好**:简单易用的 API 设计
|
||||
- **生态兼容**:充分利用 AI SDK 生态系统
|
||||
|
||||
### 12.3 成功关键
|
||||
1. **保持简单**:专注核心功能,避免过度设计
|
||||
2. **充分测试**:确保功能完整性和稳定性
|
||||
3. **渐进迁移**:平滑过渡,降低风险
|
||||
4. **文档完善**:支持快速上手和深度使用
|
||||
|
||||
这个简化的架构为 Cherry Studio 提供了一个轻量、高效、可维护的 AI 基础设施,同时为社区贡献了一个高质量的开源包。
|
||||
114
packages/aiCore/README.md
Normal file
114
packages/aiCore/README.md
Normal file
@ -0,0 +1,114 @@
|
||||
# @cherry-studio/ai-core
|
||||
|
||||
Cherry Studio AI Core 是一个基于 Vercel AI SDK 的统一 AI Provider 接口包。
|
||||
|
||||
## 特性
|
||||
|
||||
- 🚀 统一的 AI Provider 接口
|
||||
- 🔄 动态导入支持
|
||||
- 💾 智能缓存机制
|
||||
- 🛠️ TypeScript 支持
|
||||
- 📦 轻量级设计
|
||||
|
||||
## 支持的 Providers
|
||||
|
||||
基于 [AI SDK 官方支持的 providers](https://ai-sdk.dev/providers/ai-sdk-providers):
|
||||
|
||||
**核心 Providers:**
|
||||
- OpenAI
|
||||
- Anthropic
|
||||
- Google Generative AI
|
||||
- Google Vertex AI
|
||||
- Mistral AI
|
||||
- xAI (Grok)
|
||||
- Azure OpenAI
|
||||
- Amazon Bedrock
|
||||
|
||||
**扩展 Providers:**
|
||||
- Cohere
|
||||
- Groq
|
||||
- Together.ai
|
||||
- Fireworks
|
||||
- DeepSeek
|
||||
- Cerebras
|
||||
- DeepInfra
|
||||
- Replicate
|
||||
- Perplexity
|
||||
- Fal AI
|
||||
- Vercel
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
npm install @cherry-studio/ai-core ai
|
||||
```
|
||||
|
||||
还需要安装你要使用的 AI SDK provider:
|
||||
|
||||
```bash
|
||||
npm install @ai-sdk/openai @ai-sdk/anthropic @ai-sdk/google
|
||||
```
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 基础用法
|
||||
|
||||
```typescript
|
||||
import { createAiSdkClient } from '@cherry-studio/ai-core'
|
||||
|
||||
// 创建 OpenAI 客户端
|
||||
const client = await createAiSdkClient('openai', {
|
||||
apiKey: 'your-api-key'
|
||||
})
|
||||
|
||||
// 流式生成
|
||||
const result = await client.stream({
|
||||
modelId: 'gpt-4',
|
||||
messages: [
|
||||
{ role: 'user', content: 'Hello!' }
|
||||
]
|
||||
})
|
||||
|
||||
// 非流式生成
|
||||
const response = await client.generate({
|
||||
modelId: 'gpt-4',
|
||||
messages: [
|
||||
{ role: 'user', content: 'Hello!' }
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
### 便捷函数
|
||||
|
||||
```typescript
|
||||
import { createOpenAIClient, streamGeneration } from '@cherry-studio/ai-core'
|
||||
|
||||
// 快速创建 OpenAI 客户端
|
||||
const client = await createOpenAIClient({
|
||||
apiKey: 'your-api-key'
|
||||
})
|
||||
|
||||
// 便捷流式生成
|
||||
const result = await streamGeneration(
|
||||
'openai',
|
||||
'gpt-4',
|
||||
[{ role: 'user', content: 'Hello!' }],
|
||||
{ apiKey: 'your-api-key' }
|
||||
)
|
||||
```
|
||||
|
||||
### 多 Provider 支持
|
||||
|
||||
```typescript
|
||||
import { createAiSdkClient } from '@cherry-studio/ai-core'
|
||||
|
||||
// 支持多种 AI providers
|
||||
const openaiClient = await createAiSdkClient('openai', { apiKey: 'openai-key' })
|
||||
const anthropicClient = await createAiSdkClient('anthropic', { apiKey: 'anthropic-key' })
|
||||
const googleClient = await createAiSdkClient('google', { apiKey: 'google-key' })
|
||||
const xaiClient = await createAiSdkClient('xai', { apiKey: 'xai-key' })
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
117
packages/aiCore/package.json
Normal file
117
packages/aiCore/package.json
Normal file
@ -0,0 +1,117 @@
|
||||
{
|
||||
"name": "@cherry-studio/ai-core",
|
||||
"version": "1.0.0",
|
||||
"description": "Cherry Studio AI Core - Unified AI Provider Interface Based on Vercel AI SDK",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc -w",
|
||||
"clean": "rm -rf dist"
|
||||
},
|
||||
"keywords": [
|
||||
"ai",
|
||||
"sdk",
|
||||
"openai",
|
||||
"anthropic",
|
||||
"google",
|
||||
"cherry-studio",
|
||||
"vercel-ai-sdk"
|
||||
],
|
||||
"author": "Cherry Studio",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ai-sdk/amazon-bedrock": "^2.2.10",
|
||||
"@ai-sdk/anthropic": "^1.2.12",
|
||||
"@ai-sdk/azure": "^1.3.23",
|
||||
"@ai-sdk/cerebras": "^0.2.14",
|
||||
"@ai-sdk/cohere": "^1.2.10",
|
||||
"@ai-sdk/deepinfra": "^0.2.15",
|
||||
"@ai-sdk/deepseek": "^0.2.14",
|
||||
"@ai-sdk/fal": "^0.1.12",
|
||||
"@ai-sdk/fireworks": "^0.2.14",
|
||||
"@ai-sdk/google": "^1.2.19",
|
||||
"@ai-sdk/google-vertex": "^2.2.24",
|
||||
"@ai-sdk/groq": "^1.2.9",
|
||||
"@ai-sdk/mistral": "^1.2.8",
|
||||
"@ai-sdk/openai": "^1.3.22",
|
||||
"@ai-sdk/perplexity": "^1.1.9",
|
||||
"@ai-sdk/replicate": "^0.2.8",
|
||||
"@ai-sdk/togetherai": "^0.2.14",
|
||||
"@ai-sdk/vercel": "^0.0.1",
|
||||
"@ai-sdk/xai": "^1.2.16",
|
||||
"ai": "^4.3.16"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@ai-sdk/amazon-bedrock": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/anthropic": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/azure": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/cerebras": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/cohere": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/deepinfra": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/deepseek": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/fal": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/fireworks": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/google": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/google-vertex": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/groq": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/mistral": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/openai": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/perplexity": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/replicate": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/together": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/vercel": {
|
||||
"optional": true
|
||||
},
|
||||
"@ai-sdk/xai": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
341
packages/aiCore/src/clients/ApiClientFactory.ts
Normal file
341
packages/aiCore/src/clients/ApiClientFactory.ts
Normal file
@ -0,0 +1,341 @@
|
||||
/**
|
||||
* API Client Factory
|
||||
* 整合现有实现的改进版API客户端工厂
|
||||
*/
|
||||
|
||||
import { aiProviderRegistry } from '../providers/registry'
|
||||
import type { CacheStats as BaseCacheStats, ClientConfig as BaseClientConfig } from '../providers/types'
|
||||
import { UniversalAiSdkClient } from './UniversalAiSdkClient'
|
||||
|
||||
// 客户端配置接口
|
||||
export interface ClientConfig extends BaseClientConfig {}
|
||||
|
||||
// 缓存统计信息
|
||||
export interface CacheStats extends BaseCacheStats {}
|
||||
|
||||
// 错误类型
|
||||
export class ClientFactoryError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public providerId?: string,
|
||||
public cause?: Error
|
||||
) {
|
||||
super(message)
|
||||
this.name = 'ClientFactoryError'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API Client Factory
|
||||
* 统一管理和创建AI SDK客户端
|
||||
*/
|
||||
export class ApiClientFactory {
|
||||
private static instance: ApiClientFactory
|
||||
private static sdkClients = new Map<string, UniversalAiSdkClient>()
|
||||
private static lastCleanup = new Date()
|
||||
|
||||
private constructor() {
|
||||
// Private constructor for singleton pattern
|
||||
}
|
||||
|
||||
public static getInstance(): ApiClientFactory {
|
||||
if (!ApiClientFactory.instance) {
|
||||
ApiClientFactory.instance = new ApiClientFactory()
|
||||
}
|
||||
return ApiClientFactory.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* [NEW METHOD] Create a new universal client for ai-sdk providers.
|
||||
* [新方法] 为 ai-sdk 提供商创建一个新的通用客户端。
|
||||
*/
|
||||
static async createAiSdkClient(providerId: string, options: any = {}): Promise<UniversalAiSdkClient> {
|
||||
try {
|
||||
// 验证provider是否支持
|
||||
if (!aiProviderRegistry.isSupported(providerId)) {
|
||||
throw new ClientFactoryError(`Provider "${providerId}" is not supported`, providerId)
|
||||
}
|
||||
|
||||
// 生成缓存键 - 对于有认证选项的providers,使用更精细的键
|
||||
const cacheKey = this.generateCacheKey(providerId, options)
|
||||
|
||||
// 检查缓存
|
||||
if (this.sdkClients.has(cacheKey)) {
|
||||
const cachedClient = this.sdkClients.get(cacheKey)!
|
||||
// 验证缓存的客户端是否仍然有效
|
||||
if (cachedClient.isInitialized() && cachedClient.validateConfig()) {
|
||||
return cachedClient
|
||||
} else {
|
||||
// 如果缓存的客户端无效,清理它
|
||||
this.sdkClients.delete(cacheKey)
|
||||
cachedClient.cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 创建一个新的通用客户端实例
|
||||
const client = new UniversalAiSdkClient(providerId, options)
|
||||
|
||||
// 2. 初始化它(这将执行动态导入)
|
||||
await client.initialize()
|
||||
|
||||
// 3. 验证配置
|
||||
if (!client.validateConfig()) {
|
||||
throw new ClientFactoryError(`Invalid configuration for provider "${providerId}"`, providerId)
|
||||
}
|
||||
|
||||
// 4. 缓存并返回
|
||||
this.sdkClients.set(cacheKey, client)
|
||||
return client
|
||||
} catch (error) {
|
||||
if (error instanceof ClientFactoryError) {
|
||||
throw error
|
||||
}
|
||||
throw new ClientFactoryError(
|
||||
`Failed to create client for provider "${providerId}": ${error instanceof Error ? error.message : 'Unknown error'}`,
|
||||
providerId,
|
||||
error instanceof Error ? error : undefined
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存的客户端
|
||||
*/
|
||||
static getCachedClient(providerId: string, options: any = {}): UniversalAiSdkClient | undefined {
|
||||
const cacheKey = this.generateCacheKey(providerId, options)
|
||||
return this.sdkClients.get(cacheKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查客户端是否存在于缓存中
|
||||
*/
|
||||
static hasCachedClient(providerId: string, options: any = {}): boolean {
|
||||
const cacheKey = this.generateCacheKey(providerId, options)
|
||||
return this.sdkClients.has(cacheKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成缓存键
|
||||
*/
|
||||
private static generateCacheKey(providerId: string, options: any): string {
|
||||
// 创建一个包含关键配置的键,但不包含敏感信息的完整内容
|
||||
const keyData = {
|
||||
providerId,
|
||||
apiKey: options.apiKey ? this.hashApiKey(options.apiKey) : undefined,
|
||||
baseURL: options.baseURL,
|
||||
organization: options.organization,
|
||||
project: options.project,
|
||||
// 添加其他相关但非敏感的配置
|
||||
model: options.model,
|
||||
region: options.region
|
||||
}
|
||||
|
||||
// 移除undefined值
|
||||
Object.keys(keyData).forEach((key) => {
|
||||
if (keyData[key as keyof typeof keyData] === undefined) {
|
||||
delete keyData[key as keyof typeof keyData]
|
||||
}
|
||||
})
|
||||
|
||||
return JSON.stringify(keyData)
|
||||
}
|
||||
|
||||
/**
|
||||
* 对API Key进行哈希处理(用于缓存键)
|
||||
*/
|
||||
private static hashApiKey(apiKey: string): string {
|
||||
// 简单的哈希方法,只取前8个字符和后4个字符
|
||||
if (apiKey.length <= 12) {
|
||||
return apiKey.slice(0, 4) + '...'
|
||||
}
|
||||
return apiKey.slice(0, 8) + '...' + apiKey.slice(-4)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理缓存
|
||||
*/
|
||||
static clearCache(): void {
|
||||
// 清理所有客户端
|
||||
this.sdkClients.forEach((client) => {
|
||||
try {
|
||||
client.cleanup()
|
||||
} catch (error) {
|
||||
console.warn('Error cleaning up client:', error)
|
||||
}
|
||||
})
|
||||
|
||||
this.sdkClients.clear()
|
||||
this.lastCleanup = new Date()
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理特定provider的缓存
|
||||
*/
|
||||
static clearProviderCache(providerId: string): void {
|
||||
const keysToDelete: string[] = []
|
||||
|
||||
this.sdkClients.forEach((client, key) => {
|
||||
if (key.includes(`"providerId":"${providerId}"`)) {
|
||||
try {
|
||||
client.cleanup()
|
||||
} catch (error) {
|
||||
console.warn(`Error cleaning up client for ${providerId}:`, error)
|
||||
}
|
||||
keysToDelete.push(key)
|
||||
}
|
||||
})
|
||||
|
||||
keysToDelete.forEach((key) => {
|
||||
this.sdkClients.delete(key)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存统计信息
|
||||
*/
|
||||
static getCacheStats(): CacheStats {
|
||||
return {
|
||||
size: this.sdkClients.size,
|
||||
keys: Array.from(this.sdkClients.keys()),
|
||||
lastCleanup: this.lastCleanup
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预热指定的客户端
|
||||
*/
|
||||
static async warmupClients(configs: ClientConfig[]): Promise<void> {
|
||||
const warmupPromises = configs.map(async (config) => {
|
||||
try {
|
||||
const { providerId, ...options } = config
|
||||
await this.createAiSdkClient(providerId, options)
|
||||
console.log(`✅ Warmed up client for provider: ${providerId}`)
|
||||
} catch (error) {
|
||||
console.warn(`⚠️ Failed to warm up client for ${config.providerId}:`, error)
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.allSettled(warmupPromises)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有支持的providers信息
|
||||
*/
|
||||
static getSupportedProviders(): Array<{
|
||||
id: string
|
||||
name: string
|
||||
hasCachedClient: boolean
|
||||
}> {
|
||||
const providers = aiProviderRegistry.getAllProviders()
|
||||
|
||||
return providers.map((provider) => ({
|
||||
id: provider.id,
|
||||
name: provider.name,
|
||||
hasCachedClient: Array.from(this.sdkClients.keys()).some((key) => key.includes(`"providerId":"${provider.id}"`))
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量创建客户端
|
||||
*/
|
||||
static async createMultipleClients(configs: ClientConfig[]): Promise<{
|
||||
success: Array<{ providerId: string; client: UniversalAiSdkClient }>
|
||||
errors: Array<{ providerId: string; error: Error }>
|
||||
}> {
|
||||
const success: Array<{ providerId: string; client: UniversalAiSdkClient }> = []
|
||||
const errors: Array<{ providerId: string; error: Error }> = []
|
||||
|
||||
await Promise.allSettled(
|
||||
configs.map(async (config) => {
|
||||
try {
|
||||
const { providerId, ...options } = config
|
||||
const client = await this.createAiSdkClient(providerId, options)
|
||||
success.push({ providerId, client })
|
||||
} catch (error) {
|
||||
errors.push({
|
||||
providerId: config.providerId,
|
||||
error: error instanceof Error ? error : new Error('Unknown error')
|
||||
})
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
return { success, errors }
|
||||
}
|
||||
|
||||
/**
|
||||
* 健康检查 - 检查所有缓存客户端的状态
|
||||
*/
|
||||
static async healthCheck(): Promise<{
|
||||
healthy: number
|
||||
unhealthy: number
|
||||
total: number
|
||||
details: Array<{
|
||||
providerId: string
|
||||
status: 'healthy' | 'unhealthy'
|
||||
error?: string
|
||||
}>
|
||||
}> {
|
||||
const details: Array<{
|
||||
providerId: string
|
||||
status: 'healthy' | 'unhealthy'
|
||||
error?: string
|
||||
}> = []
|
||||
|
||||
let healthy = 0
|
||||
let unhealthy = 0
|
||||
|
||||
for (const [, client] of this.sdkClients) {
|
||||
try {
|
||||
const info = client.getProviderInfo()
|
||||
if (client.isInitialized() && client.validateConfig()) {
|
||||
healthy++
|
||||
details.push({
|
||||
providerId: info.id,
|
||||
status: 'healthy'
|
||||
})
|
||||
} else {
|
||||
unhealthy++
|
||||
details.push({
|
||||
providerId: info.id,
|
||||
status: 'unhealthy',
|
||||
error: 'Client not properly initialized or invalid config'
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
unhealthy++
|
||||
details.push({
|
||||
providerId: 'unknown',
|
||||
status: 'unhealthy',
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
healthy,
|
||||
unhealthy,
|
||||
total: this.sdkClients.size,
|
||||
details
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例实例和便捷函数
|
||||
export const apiClientFactory = ApiClientFactory.getInstance()
|
||||
|
||||
// 便捷函数
|
||||
export const createAiSdkClient = (providerId: string, options?: any) =>
|
||||
ApiClientFactory.createAiSdkClient(providerId, options)
|
||||
|
||||
export const getCachedClient = (providerId: string, options?: any) =>
|
||||
ApiClientFactory.getCachedClient(providerId, options)
|
||||
|
||||
export const clearCache = () => ApiClientFactory.clearCache()
|
||||
|
||||
export const warmupClients = (configs: ClientConfig[]) => ApiClientFactory.warmupClients(configs)
|
||||
|
||||
export const healthCheck = () => ApiClientFactory.healthCheck()
|
||||
|
||||
// 默认导出
|
||||
export default ApiClientFactory
|
||||
201
packages/aiCore/src/clients/UniversalAiSdkClient.ts
Normal file
201
packages/aiCore/src/clients/UniversalAiSdkClient.ts
Normal file
@ -0,0 +1,201 @@
|
||||
/**
|
||||
* Universal AI SDK Client
|
||||
* 基于现有实现的简化版统一AI SDK客户端
|
||||
*/
|
||||
|
||||
import { generateText, streamText } from 'ai'
|
||||
|
||||
import { aiProviderRegistry } from '../providers/registry'
|
||||
|
||||
/**
|
||||
* Universal AI SDK Client
|
||||
* 统一的AI SDK客户端实现
|
||||
*/
|
||||
export class UniversalAiSdkClient {
|
||||
private provider: any // The instantiated provider (e.g., from createOpenAI)
|
||||
private initialized = false
|
||||
private providerConfig: any
|
||||
|
||||
constructor(
|
||||
private providerName: string,
|
||||
private options: any // API keys, etc.
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 初始化客户端 - 异步步骤,因为涉及动态导入
|
||||
*/
|
||||
async initialize(): Promise<void> {
|
||||
if (this.initialized) return
|
||||
|
||||
// 获取Provider配置
|
||||
this.providerConfig = aiProviderRegistry.getProvider(this.providerName)
|
||||
if (!this.providerConfig) {
|
||||
throw new Error(`Provider "${this.providerName}" is not registered.`)
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用注册表的动态导入功能
|
||||
const module = await this.providerConfig.import()
|
||||
|
||||
// 获取创建函数
|
||||
const creatorFunction = module[this.providerConfig.creatorFunctionName]
|
||||
|
||||
if (typeof creatorFunction !== 'function') {
|
||||
throw new Error(
|
||||
`Creator function "${this.providerConfig.creatorFunctionName}" not found in the imported module for provider "${this.providerName}".`
|
||||
)
|
||||
}
|
||||
|
||||
// 创建provider实例
|
||||
this.provider = creatorFunction(this.options)
|
||||
this.initialized = true
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new Error(`Failed to initialize provider "${this.providerName}": ${error.message}`)
|
||||
}
|
||||
throw new Error(`An unknown error occurred while initializing provider "${this.providerName}".`)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否已初始化
|
||||
*/
|
||||
isInitialized(): boolean {
|
||||
return this.initialized
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取特定模型实例的辅助方法
|
||||
*/
|
||||
private getModel(modelId: string): any {
|
||||
if (!this.initialized) throw new Error('Client not initialized')
|
||||
|
||||
// 大多数providers都有直接调用模式:provider(modelId)
|
||||
if (typeof this.provider === 'function') {
|
||||
return this.provider(modelId)
|
||||
}
|
||||
|
||||
throw new Error(`Unknown model access pattern for provider "${this.providerName}"`)
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现流式逻辑,使用核心ai-sdk函数
|
||||
*/
|
||||
async stream(request: any): Promise<any> {
|
||||
if (!this.initialized) await this.initialize()
|
||||
|
||||
const model = this.getModel(request.modelId)
|
||||
|
||||
// 直接调用标准ai-sdk函数
|
||||
return streamText({
|
||||
model,
|
||||
...request
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现非流式逻辑
|
||||
*/
|
||||
async generate(request: any): Promise<any> {
|
||||
if (!this.initialized) await this.initialize()
|
||||
|
||||
const model = this.getModel(request.modelId)
|
||||
|
||||
return generateText({
|
||||
model,
|
||||
...request
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证配置
|
||||
*/
|
||||
validateConfig(): boolean {
|
||||
try {
|
||||
// 基础验证
|
||||
if (!this.providerName) return false
|
||||
if (!this.providerConfig) return false
|
||||
|
||||
// API Key验证(如果需要)
|
||||
if (this.requiresApiKey() && !this.options?.apiKey) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Provider是否需要API Key
|
||||
*/
|
||||
private requiresApiKey(): boolean {
|
||||
// 大多数云服务Provider都需要API Key
|
||||
const noApiKeyProviders = ['local', 'ollama'] // 本地运行的Provider
|
||||
return !noApiKeyProviders.includes(this.providerName)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Provider信息
|
||||
*/
|
||||
getProviderInfo(): {
|
||||
id: string
|
||||
name: string
|
||||
isInitialized: boolean
|
||||
} {
|
||||
return {
|
||||
id: this.providerName,
|
||||
name: this.providerConfig?.name || this.providerName,
|
||||
isInitialized: this.initialized
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理资源
|
||||
*/
|
||||
cleanup(): void {
|
||||
this.provider = null
|
||||
this.initialized = false
|
||||
this.providerConfig = null
|
||||
}
|
||||
}
|
||||
|
||||
// 工厂函数,方便创建客户端
|
||||
export async function createUniversalClient(providerName: string, options: any = {}): Promise<UniversalAiSdkClient> {
|
||||
const client = new UniversalAiSdkClient(providerName, options)
|
||||
await client.initialize()
|
||||
return client
|
||||
}
|
||||
|
||||
// 便捷的流式生成函数
|
||||
export async function streamGeneration(
|
||||
providerName: string,
|
||||
modelId: string,
|
||||
messages: any[],
|
||||
options: any = {}
|
||||
): Promise<any> {
|
||||
const client = await createUniversalClient(providerName, options)
|
||||
|
||||
return client.stream({
|
||||
modelId,
|
||||
messages,
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// 便捷的非流式生成函数
|
||||
export async function generateCompletion(
|
||||
providerName: string,
|
||||
modelId: string,
|
||||
messages: any[],
|
||||
options: any = {}
|
||||
): Promise<any> {
|
||||
const client = await createUniversalClient(providerName, options)
|
||||
|
||||
return client.generate({
|
||||
modelId,
|
||||
messages,
|
||||
...options
|
||||
})
|
||||
}
|
||||
130
packages/aiCore/src/index.ts
Normal file
130
packages/aiCore/src/index.ts
Normal file
@ -0,0 +1,130 @@
|
||||
/**
|
||||
* Cherry Studio AI Core Package
|
||||
* 基于 Vercel AI SDK 的统一 AI Provider 接口
|
||||
*/
|
||||
|
||||
// 核心导出
|
||||
export { ApiClientFactory, apiClientFactory } from './clients/ApiClientFactory'
|
||||
export { UniversalAiSdkClient } from './clients/UniversalAiSdkClient'
|
||||
export { aiProviderRegistry, PROVIDER_REGISTRY } from './providers/registry'
|
||||
|
||||
// 类型导出
|
||||
export type { CacheStats, ClientConfig, ClientFactoryError } from './clients/ApiClientFactory'
|
||||
export type { ProviderConfig } from './providers/registry'
|
||||
export type { ProviderError } from './providers/types'
|
||||
|
||||
// 便捷函数导出
|
||||
export { clearCache, createAiSdkClient, getCachedClient, healthCheck, warmupClients } from './clients/ApiClientFactory'
|
||||
export { createUniversalClient, generateCompletion, streamGeneration } from './clients/UniversalAiSdkClient'
|
||||
export { getAllProviders, getProvider, isProviderSupported, registerProvider } from './providers/registry'
|
||||
|
||||
// 默认导出 - 主要的工厂类
|
||||
export { ApiClientFactory as default } from './clients/ApiClientFactory'
|
||||
|
||||
// 导入内部使用的函数
|
||||
import { ApiClientFactory } from './clients/ApiClientFactory'
|
||||
import { clearCache, createAiSdkClient, healthCheck } from './clients/ApiClientFactory'
|
||||
import { aiProviderRegistry } from './providers/registry'
|
||||
import { getAllProviders, isProviderSupported } from './providers/registry'
|
||||
|
||||
// 包信息
|
||||
export const AI_CORE_VERSION = '1.0.0'
|
||||
export const AI_CORE_NAME = '@cherry-studio/ai-core'
|
||||
|
||||
// 包配置和实用工具
|
||||
export const AiCore = {
|
||||
version: AI_CORE_VERSION,
|
||||
name: AI_CORE_NAME,
|
||||
|
||||
// 快速创建客户端
|
||||
async createClient(providerId: string, options: any = {}) {
|
||||
return createAiSdkClient(providerId, options)
|
||||
},
|
||||
|
||||
// 获取支持的providers
|
||||
getSupportedProviders() {
|
||||
return getAllProviders()
|
||||
},
|
||||
|
||||
// 检查provider支持
|
||||
isSupported(providerId: string) {
|
||||
return isProviderSupported(providerId)
|
||||
},
|
||||
|
||||
// 获取缓存统计
|
||||
getCacheStats() {
|
||||
return ApiClientFactory.getCacheStats()
|
||||
},
|
||||
|
||||
// 健康检查
|
||||
async healthCheck() {
|
||||
return healthCheck()
|
||||
},
|
||||
|
||||
// 清理所有资源
|
||||
cleanup() {
|
||||
clearCache()
|
||||
aiProviderRegistry.cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
// 便捷的预配置clients创建函数
|
||||
export const createOpenAIClient = async (options: { apiKey: string; baseURL?: string }) => {
|
||||
return createAiSdkClient('openai', options)
|
||||
}
|
||||
|
||||
export const createAnthropicClient = async (options: { apiKey: string; baseURL?: string }) => {
|
||||
return createAiSdkClient('anthropic', options)
|
||||
}
|
||||
|
||||
export const createGoogleClient = async (options: { apiKey: string; baseURL?: string }) => {
|
||||
return createAiSdkClient('google', options)
|
||||
}
|
||||
|
||||
export const createXAIClient = async (options: { apiKey: string; baseURL?: string }) => {
|
||||
return createAiSdkClient('xai', options)
|
||||
}
|
||||
|
||||
// 调试和开发工具
|
||||
export const DevTools = {
|
||||
// 列出所有注册的providers
|
||||
listProviders() {
|
||||
return aiProviderRegistry.getAllProviders().map((p) => ({
|
||||
id: p.id,
|
||||
name: p.name
|
||||
}))
|
||||
},
|
||||
|
||||
// 测试provider连接
|
||||
async testProvider(providerId: string, options: any) {
|
||||
try {
|
||||
const client = await createAiSdkClient(providerId, options)
|
||||
const info = client.getProviderInfo()
|
||||
return {
|
||||
success: true,
|
||||
providerId: info.id,
|
||||
name: info.name,
|
||||
isInitialized: info.isInitialized
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
providerId,
|
||||
error: error instanceof Error ? error.message : 'Unknown error'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 获取详细的缓存信息
|
||||
getCacheDetails() {
|
||||
const stats = ApiClientFactory.getCacheStats()
|
||||
const providers = aiProviderRegistry.getAllProviders()
|
||||
|
||||
return {
|
||||
cacheStats: stats,
|
||||
supportedProviders: providers.length,
|
||||
registeredProviders: aiProviderRegistry.getAllProviders().length,
|
||||
activeClients: stats.size
|
||||
}
|
||||
}
|
||||
}
|
||||
226
packages/aiCore/src/providers/registry.ts
Normal file
226
packages/aiCore/src/providers/registry.ts
Normal file
@ -0,0 +1,226 @@
|
||||
/**
|
||||
* AI Provider 注册表
|
||||
* 统一管理所有 AI SDK Providers 的动态导入和工厂函数
|
||||
*/
|
||||
|
||||
// Provider 配置接口(简化版)
|
||||
export interface ProviderConfig {
|
||||
id: string
|
||||
name: string
|
||||
// 动态导入函数
|
||||
import: () => Promise<any>
|
||||
// 创建函数名称
|
||||
creatorFunctionName: string
|
||||
}
|
||||
|
||||
/**
|
||||
* AI SDK Provider 注册表
|
||||
* 管理所有支持的 AI Providers 及其动态导入
|
||||
*/
|
||||
export class AiProviderRegistry {
|
||||
private static instance: AiProviderRegistry
|
||||
private registry = new Map<string, ProviderConfig>()
|
||||
|
||||
private constructor() {
|
||||
this.initializeProviders()
|
||||
}
|
||||
|
||||
public static getInstance(): AiProviderRegistry {
|
||||
if (!AiProviderRegistry.instance) {
|
||||
AiProviderRegistry.instance = new AiProviderRegistry()
|
||||
}
|
||||
return AiProviderRegistry.instance
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化所有支持的 Providers
|
||||
* 基于 AI SDK 官方文档: https://ai-sdk.dev/providers/ai-sdk-providers
|
||||
*/
|
||||
private initializeProviders(): void {
|
||||
const providers: ProviderConfig[] = [
|
||||
// 核心 AI SDK Providers
|
||||
{
|
||||
id: 'openai',
|
||||
name: 'OpenAI',
|
||||
import: () => import('@ai-sdk/openai'),
|
||||
creatorFunctionName: 'createOpenAI'
|
||||
},
|
||||
{
|
||||
id: 'anthropic',
|
||||
name: 'Anthropic',
|
||||
import: () => import('@ai-sdk/anthropic'),
|
||||
creatorFunctionName: 'createAnthropic'
|
||||
},
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google Generative AI',
|
||||
import: () => import('@ai-sdk/google'),
|
||||
creatorFunctionName: 'createGoogleGenerativeAI'
|
||||
},
|
||||
{
|
||||
id: 'google-vertex',
|
||||
name: 'Google Vertex AI',
|
||||
import: () => import('@ai-sdk/google-vertex'),
|
||||
creatorFunctionName: 'createVertex'
|
||||
},
|
||||
{
|
||||
id: 'mistral',
|
||||
name: 'Mistral AI',
|
||||
import: () => import('@ai-sdk/mistral'),
|
||||
creatorFunctionName: 'createMistral'
|
||||
},
|
||||
{
|
||||
id: 'xai',
|
||||
name: 'xAI (Grok)',
|
||||
import: () => import('@ai-sdk/xai'),
|
||||
creatorFunctionName: 'createXai'
|
||||
},
|
||||
{
|
||||
id: 'azure',
|
||||
name: 'Azure OpenAI',
|
||||
import: () => import('@ai-sdk/azure'),
|
||||
creatorFunctionName: 'createAzure'
|
||||
},
|
||||
{
|
||||
id: 'bedrock',
|
||||
name: 'Amazon Bedrock',
|
||||
import: () => import('@ai-sdk/amazon-bedrock'),
|
||||
creatorFunctionName: 'createAmazonBedrock'
|
||||
},
|
||||
{
|
||||
id: 'cohere',
|
||||
name: 'Cohere',
|
||||
import: () => import('@ai-sdk/cohere'),
|
||||
creatorFunctionName: 'createCohere'
|
||||
},
|
||||
{
|
||||
id: 'groq',
|
||||
name: 'Groq',
|
||||
import: () => import('@ai-sdk/groq'),
|
||||
creatorFunctionName: 'createGroq'
|
||||
},
|
||||
{
|
||||
id: 'together',
|
||||
name: 'Together.ai',
|
||||
import: () => import('@ai-sdk/togetherai'),
|
||||
creatorFunctionName: 'createTogetherAI'
|
||||
},
|
||||
{
|
||||
id: 'fireworks',
|
||||
name: 'Fireworks',
|
||||
import: () => import('@ai-sdk/fireworks'),
|
||||
creatorFunctionName: 'createFireworks'
|
||||
},
|
||||
{
|
||||
id: 'deepseek',
|
||||
name: 'DeepSeek',
|
||||
import: () => import('@ai-sdk/deepseek'),
|
||||
creatorFunctionName: 'createDeepSeek'
|
||||
},
|
||||
{
|
||||
id: 'cerebras',
|
||||
name: 'Cerebras',
|
||||
import: () => import('@ai-sdk/cerebras'),
|
||||
creatorFunctionName: 'createCerebras'
|
||||
},
|
||||
{
|
||||
id: 'deepinfra',
|
||||
name: 'DeepInfra',
|
||||
import: () => import('@ai-sdk/deepinfra'),
|
||||
creatorFunctionName: 'createDeepInfra'
|
||||
},
|
||||
{
|
||||
id: 'replicate',
|
||||
name: 'Replicate',
|
||||
import: () => import('@ai-sdk/replicate'),
|
||||
creatorFunctionName: 'createReplicate'
|
||||
},
|
||||
{
|
||||
id: 'perplexity',
|
||||
name: 'Perplexity',
|
||||
import: () => import('@ai-sdk/perplexity'),
|
||||
creatorFunctionName: 'createPerplexity'
|
||||
},
|
||||
{
|
||||
id: 'fal',
|
||||
name: 'Fal AI',
|
||||
import: () => import('@ai-sdk/fal'),
|
||||
creatorFunctionName: 'createFal'
|
||||
},
|
||||
{
|
||||
id: 'vercel',
|
||||
name: 'Vercel',
|
||||
import: () => import('@ai-sdk/vercel'),
|
||||
creatorFunctionName: 'createVercel'
|
||||
}
|
||||
]
|
||||
|
||||
// 初始化注册表
|
||||
providers.forEach((config) => {
|
||||
this.registry.set(config.id, config)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已注册的 Providers
|
||||
*/
|
||||
public getAllProviders(): ProviderConfig[] {
|
||||
return Array.from(this.registry.values())
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 ID 获取 Provider 配置
|
||||
*/
|
||||
public getProvider(id: string): ProviderConfig | undefined {
|
||||
return this.registry.get(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 Provider 是否支持(是否已注册)
|
||||
*/
|
||||
public isSupported(id: string): boolean {
|
||||
return this.registry.has(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册新的 Provider(用于扩展)
|
||||
*/
|
||||
public registerProvider(config: ProviderConfig): void {
|
||||
this.registry.set(config.id, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理资源
|
||||
*/
|
||||
public cleanup(): void {
|
||||
this.registry.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取兼容现有实现的注册表格式
|
||||
*/
|
||||
public getCompatibleRegistry(): Record<string, { import: () => Promise<any>; creatorFunctionName: string }> {
|
||||
const compatibleRegistry: Record<string, { import: () => Promise<any>; creatorFunctionName: string }> = {}
|
||||
|
||||
this.getAllProviders().forEach((provider) => {
|
||||
compatibleRegistry[provider.id] = {
|
||||
import: provider.import,
|
||||
creatorFunctionName: provider.creatorFunctionName
|
||||
}
|
||||
})
|
||||
|
||||
return compatibleRegistry
|
||||
}
|
||||
}
|
||||
|
||||
// 导出单例实例
|
||||
export const aiProviderRegistry = AiProviderRegistry.getInstance()
|
||||
|
||||
// 便捷函数
|
||||
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 PROVIDER_REGISTRY = aiProviderRegistry.getCompatibleRegistry()
|
||||
47
packages/aiCore/src/providers/types.ts
Normal file
47
packages/aiCore/src/providers/types.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Provider 相关核心类型定义
|
||||
* 只定义必要的接口,其他类型直接使用 AI SDK
|
||||
*/
|
||||
|
||||
// Provider 配置接口(简化版)
|
||||
export interface ProviderConfig {
|
||||
id: string
|
||||
name: string
|
||||
import: () => Promise<any>
|
||||
creatorFunctionName: string
|
||||
}
|
||||
|
||||
// API 客户端工厂接口
|
||||
export interface ApiClientFactory {
|
||||
createAiSdkClient(providerId: string, options?: any): Promise<any>
|
||||
getCachedClient(providerId: string, options?: any): any
|
||||
clearCache(): void
|
||||
}
|
||||
|
||||
// 客户端配置
|
||||
export interface ClientConfig {
|
||||
providerId: string
|
||||
apiKey?: string
|
||||
baseURL?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
// 错误类型
|
||||
export class ProviderError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public providerId: string,
|
||||
public code?: string,
|
||||
public cause?: Error
|
||||
) {
|
||||
super(message)
|
||||
this.name = 'ProviderError'
|
||||
}
|
||||
}
|
||||
|
||||
// 缓存统计信息
|
||||
export interface CacheStats {
|
||||
size: number
|
||||
keys: string[]
|
||||
lastCleanup?: Date
|
||||
}
|
||||
26
packages/aiCore/tsconfig.json
Normal file
26
packages/aiCore/tsconfig.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"noEmitOnError": false,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
598
yarn.lock
598
yarn.lock
@ -74,6 +74,313 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/amazon-bedrock@npm:^2.2.10":
|
||||
version: 2.2.10
|
||||
resolution: "@ai-sdk/amazon-bedrock@npm:2.2.10"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
"@smithy/eventstream-codec": "npm:^4.0.1"
|
||||
"@smithy/util-utf8": "npm:^4.0.0"
|
||||
aws4fetch: "npm:^1.0.20"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/ca066cc4dd94146374492e18e313b7664b661562e7fa3c94ad55c731564744281d62662337718fe107c99d7d2ebf8fd655c8e2cb3dcbcd30b2e33cbc248c962e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/anthropic@npm:1.2.12, @ai-sdk/anthropic@npm:^1.2.12":
|
||||
version: 1.2.12
|
||||
resolution: "@ai-sdk/anthropic@npm:1.2.12"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/da13e1ed3c03efe207dbb0fd5fe9f399e4119e6687ec1096418a33a7eeea3c5f912a51c74b185bba3c203b15ee0c1b9cdf649711815ff8e769e31af266ac00fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/azure@npm:^1.3.23":
|
||||
version: 1.3.23
|
||||
resolution: "@ai-sdk/azure@npm:1.3.23"
|
||||
dependencies:
|
||||
"@ai-sdk/openai": "npm:1.3.22"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/18fcd3271e316edffe1b289b1c148e3bf6e0e51e57440d6a5aa4d76b53831dd5219fffcedb92d7dddebac81add46151a00bf70bd9e14509421e3bb0e359fd6bf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/cerebras@npm:^0.2.14":
|
||||
version: 0.2.14
|
||||
resolution: "@ai-sdk/cerebras@npm:0.2.14"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:0.2.14"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/a94f91daa618ce3f0499b77191f53c54a5a1f8bce6b4ad12acc976e4410f83271dfb1fb377bab9dee573f497d9a505160b757ac0120d8dc160c7081618f94b45
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/cohere@npm:^1.2.10":
|
||||
version: 1.2.10
|
||||
resolution: "@ai-sdk/cohere@npm:1.2.10"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/7a7d026458322c9579d860244072525cbe939b86ad89f0cb29b0103fc8a1cb7e54b11bb5f13a4db6c18507a12a8a0b4035333c2e996d8ded4708b5ec355b78e7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/deepinfra@npm:^0.2.15":
|
||||
version: 0.2.15
|
||||
resolution: "@ai-sdk/deepinfra@npm:0.2.15"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:0.2.14"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/569a7d9fdf2d4ab16e371243782ece401d2336ed152741789e91f2df24918e536b4e1e8ee9ae9436a1fe059e00c32a06c867f083c1d93443be2a564fd465459e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/deepseek@npm:^0.2.14":
|
||||
version: 0.2.14
|
||||
resolution: "@ai-sdk/deepseek@npm:0.2.14"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:0.2.14"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/abf22e44336c2b9cf075da20d3e641bbe6584861820ebbcb37877ce4730503c561984b63040384aef53ae0b5835f6680f7c42477588ce5fdf6ad37df695e129e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/fal@npm:^0.1.12":
|
||||
version: 0.1.12
|
||||
resolution: "@ai-sdk/fal@npm:0.1.12"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/3e5f0a72cf479e017dbddafb5bcba64f51e3f7feba33045bb132a7ec3e0abe5b4b65740a0e4fc7631b7a0587f8beb8e52b94adee409e6c82db57ba5a87ab8006
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/fireworks@npm:^0.2.14":
|
||||
version: 0.2.14
|
||||
resolution: "@ai-sdk/fireworks@npm:0.2.14"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:0.2.14"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/c34dba26e0de8754017b4bc16c1b4a295863b4d18e33c5e1bf6e6057029c78cae397e610b34e1eae16af454653cbd97754b66a1f7eede9285df2e16f4637aec3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/google-vertex@npm:^2.2.24":
|
||||
version: 2.2.24
|
||||
resolution: "@ai-sdk/google-vertex@npm:2.2.24"
|
||||
dependencies:
|
||||
"@ai-sdk/anthropic": "npm:1.2.12"
|
||||
"@ai-sdk/google": "npm:1.2.19"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
google-auth-library: "npm:^9.15.0"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/720139b34e8b395d52517abdc81b54f8c6eac1334879f76c07515701bfc2c0dfec7aefb0aee3851e1ec9721462b02a3caffecc5803fd267604f5b1548b352ae3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/google@npm:1.2.19, @ai-sdk/google@npm:^1.2.19":
|
||||
version: 1.2.19
|
||||
resolution: "@ai-sdk/google@npm:1.2.19"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/b40d62ce822ce00850492e4a41c8b6b1ba2ddaaaa8f8d9b8381c198781adb23000fc4f434ef7edf5ba356a4455f8afbbdc5cbecbb0f66b7bcabbcd25758fc6b8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/groq@npm:^1.2.9":
|
||||
version: 1.2.9
|
||||
resolution: "@ai-sdk/groq@npm:1.2.9"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/b268c337fb656d6b36e2a0ee7737c073ad22521acf20b6861a51c269d4f49f59c269d6184ce21cbc61316987e46ed64696dffef57d6d60fb9c45f069d0f30297
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/mistral@npm:^1.2.8":
|
||||
version: 1.2.8
|
||||
resolution: "@ai-sdk/mistral@npm:1.2.8"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/d798ce75685f86f8a77c38745c71328fd1bd6b361601d1cb613b94c3c709e890e15e369f8b7e7b009e28394ec42c500c775ec293d506de2be08b13730ea7a924
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/openai-compatible@npm:0.2.14":
|
||||
version: 0.2.14
|
||||
resolution: "@ai-sdk/openai-compatible@npm:0.2.14"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/60980df8507c1e5d04ac51123bc15ea5cbf29eb88485f63da28d64ab5d9c3b335d2a2c9155a383605972ef5fa636929c8e2d360bf799153acf2b358e1af1fd47
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/openai@npm:1.3.22, @ai-sdk/openai@npm:^1.3.22":
|
||||
version: 1.3.22
|
||||
resolution: "@ai-sdk/openai@npm:1.3.22"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/bcc73a84bebd15aa54568c3c77cedd5f999e282c5be180d5e28ebc789f8873dd0a74d87f1ec4a0f16e3e61b658c3b0734835daf176ed910966246db73c72b468
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/perplexity@npm:^1.1.9":
|
||||
version: 1.1.9
|
||||
resolution: "@ai-sdk/perplexity@npm:1.1.9"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/02720dc2d65de771900a3b588b257ac9c3bdf8b3a9e255875b03e4ede9ef185a4c6d311782b5e8033306a6e7fde40fdec526345ba0843a84d45184a556e883ca
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/provider-utils@npm:2.2.8":
|
||||
version: 2.2.8
|
||||
resolution: "@ai-sdk/provider-utils@npm:2.2.8"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
nanoid: "npm:^3.3.8"
|
||||
secure-json-parse: "npm:^2.7.0"
|
||||
peerDependencies:
|
||||
zod: ^3.23.8
|
||||
checksum: 10c0/34c72bf5f23f2d3e7aef496da7099422ba3b3ff243c35511853e16c3f1528717500262eea32b19e3e09bc4452152a5f31e650512f53f08a5f5645d907bff429e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/provider@npm:1.1.3":
|
||||
version: 1.1.3
|
||||
resolution: "@ai-sdk/provider@npm:1.1.3"
|
||||
dependencies:
|
||||
json-schema: "npm:^0.4.0"
|
||||
checksum: 10c0/40e080e223328e7c89829865e9c48f4ce8442a6a59f7ed5dfbdb4f63e8d859a76641e2d31e91970dd389bddb910f32ec7c3dbb0ce583c119e5a1e614ea7b8bc4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/react@npm:1.2.12":
|
||||
version: 1.2.12
|
||||
resolution: "@ai-sdk/react@npm:1.2.12"
|
||||
dependencies:
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
"@ai-sdk/ui-utils": "npm:1.2.11"
|
||||
swr: "npm:^2.2.5"
|
||||
throttleit: "npm:2.1.0"
|
||||
peerDependencies:
|
||||
react: ^18 || ^19 || ^19.0.0-rc
|
||||
zod: ^3.23.8
|
||||
peerDependenciesMeta:
|
||||
zod:
|
||||
optional: true
|
||||
checksum: 10c0/5422feb4ffeebd3287441cf658733e9ad7f9081fc279e85f57700d7fe9f4ed8a0504789c1be695790df44b28730e525cf12acf0f52bfa5adecc561ffd00cb2a5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/replicate@npm:^0.2.8":
|
||||
version: 0.2.8
|
||||
resolution: "@ai-sdk/replicate@npm:0.2.8"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/96a90a815b60914126fce854dd32d5912cc4c09d418259af232214d083da8ea6857ad0c99b47758d59d2c4d845dcb33844bb97c6bd78238aee6a00c0069a5f94
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/togetherai@npm:^0.2.14":
|
||||
version: 0.2.14
|
||||
resolution: "@ai-sdk/togetherai@npm:0.2.14"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:0.2.14"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/ae8108fd81e583d7bde30cc391e048197b44dcb3881eecb69d65bc3ef8067a728e308b172587348278700e9b3235e3f6163bcdafb5bb2ec4cc87ff4f87a8e02b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/ui-utils@npm:1.2.11":
|
||||
version: 1.2.11
|
||||
resolution: "@ai-sdk/ui-utils@npm:1.2.11"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
zod-to-json-schema: "npm:^3.24.1"
|
||||
peerDependencies:
|
||||
zod: ^3.23.8
|
||||
checksum: 10c0/de0a10f9e16010126a21a1690aaf56d545b9c0f8d8b2cc33ffd22c2bb2e914949acb9b3f86e0e39a0e4b0d4f24db12e2b094045e34b311de0c8f84bfab48cc92
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/vercel@npm:^0.0.1":
|
||||
version: 0.0.1
|
||||
resolution: "@ai-sdk/vercel@npm:0.0.1"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:0.2.14"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/608a747dc2abb2fc7789cad503769dab5cdedaf39f3494a70f7dbb42ea2dcccd91827b856508faac5305486981206397faa25edca3d593f42ab38869b220835c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ai-sdk/xai@npm:^1.2.16":
|
||||
version: 1.2.16
|
||||
resolution: "@ai-sdk/xai@npm:1.2.16"
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible": "npm:0.2.14"
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
peerDependencies:
|
||||
zod: ^3.0.0
|
||||
checksum: 10c0/5418f42506679c49f8c6127b0cdf8185622ccb844d6cf928efe1f819b20cbb4eae631eb7dc534468c790fa7087438b4ebd3b4072c13fb28e0c947ebdd6628ec2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.3.0":
|
||||
version: 2.3.0
|
||||
resolution: "@ampproject/remapping@npm:2.3.0"
|
||||
@ -228,6 +535,38 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@aws-crypto/crc32@npm:5.2.0":
|
||||
version: 5.2.0
|
||||
resolution: "@aws-crypto/crc32@npm:5.2.0"
|
||||
dependencies:
|
||||
"@aws-crypto/util": "npm:^5.2.0"
|
||||
"@aws-sdk/types": "npm:^3.222.0"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/eab9581d3363af5ea498ae0e72de792f54d8890360e14a9d8261b7b5c55ebe080279fb2556e07994d785341cdaa99ab0b1ccf137832b53b5904cd6928f2b094b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@aws-crypto/util@npm:^5.2.0":
|
||||
version: 5.2.0
|
||||
resolution: "@aws-crypto/util@npm:5.2.0"
|
||||
dependencies:
|
||||
"@aws-sdk/types": "npm:^3.222.0"
|
||||
"@smithy/util-utf8": "npm:^2.0.0"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/0362d4c197b1fd64b423966945130207d1fe23e1bb2878a18e361f7743c8d339dad3f8729895a29aa34fff6a86c65f281cf5167c4bf253f21627ae80b6dd2951
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@aws-sdk/types@npm:^3.222.0":
|
||||
version: 3.821.0
|
||||
resolution: "@aws-sdk/types@npm:3.821.0"
|
||||
dependencies:
|
||||
"@smithy/types": "npm:^4.3.1"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/6202b2c0db1dd5ee78e6dc45c51f8b19deff0ee400dd5a7a15d089cc5493a2db6a6e0553ff32742e8bc810d428b36599534e14c1b466695550aef1b1d87f043d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/code-frame@npm:^7.10.4":
|
||||
version: 7.27.1
|
||||
resolution: "@babel/code-frame@npm:7.27.1"
|
||||
@ -509,6 +848,73 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cherry-studio/ai-core@workspace:packages/aiCore":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@cherry-studio/ai-core@workspace:packages/aiCore"
|
||||
dependencies:
|
||||
"@ai-sdk/amazon-bedrock": "npm:^2.2.10"
|
||||
"@ai-sdk/anthropic": "npm:^1.2.12"
|
||||
"@ai-sdk/azure": "npm:^1.3.23"
|
||||
"@ai-sdk/cerebras": "npm:^0.2.14"
|
||||
"@ai-sdk/cohere": "npm:^1.2.10"
|
||||
"@ai-sdk/deepinfra": "npm:^0.2.15"
|
||||
"@ai-sdk/deepseek": "npm:^0.2.14"
|
||||
"@ai-sdk/fal": "npm:^0.1.12"
|
||||
"@ai-sdk/fireworks": "npm:^0.2.14"
|
||||
"@ai-sdk/google": "npm:^1.2.19"
|
||||
"@ai-sdk/google-vertex": "npm:^2.2.24"
|
||||
"@ai-sdk/groq": "npm:^1.2.9"
|
||||
"@ai-sdk/mistral": "npm:^1.2.8"
|
||||
"@ai-sdk/openai": "npm:^1.3.22"
|
||||
"@ai-sdk/perplexity": "npm:^1.1.9"
|
||||
"@ai-sdk/replicate": "npm:^0.2.8"
|
||||
"@ai-sdk/togetherai": "npm:^0.2.14"
|
||||
"@ai-sdk/vercel": "npm:^0.0.1"
|
||||
"@ai-sdk/xai": "npm:^1.2.16"
|
||||
ai: "npm:^4.3.16"
|
||||
typescript: "npm:^5.0.0"
|
||||
peerDependenciesMeta:
|
||||
"@ai-sdk/amazon-bedrock":
|
||||
optional: true
|
||||
"@ai-sdk/anthropic":
|
||||
optional: true
|
||||
"@ai-sdk/azure":
|
||||
optional: true
|
||||
"@ai-sdk/cerebras":
|
||||
optional: true
|
||||
"@ai-sdk/cohere":
|
||||
optional: true
|
||||
"@ai-sdk/deepinfra":
|
||||
optional: true
|
||||
"@ai-sdk/deepseek":
|
||||
optional: true
|
||||
"@ai-sdk/fal":
|
||||
optional: true
|
||||
"@ai-sdk/fireworks":
|
||||
optional: true
|
||||
"@ai-sdk/google":
|
||||
optional: true
|
||||
"@ai-sdk/google-vertex":
|
||||
optional: true
|
||||
"@ai-sdk/groq":
|
||||
optional: true
|
||||
"@ai-sdk/mistral":
|
||||
optional: true
|
||||
"@ai-sdk/openai":
|
||||
optional: true
|
||||
"@ai-sdk/perplexity":
|
||||
optional: true
|
||||
"@ai-sdk/replicate":
|
||||
optional: true
|
||||
"@ai-sdk/together":
|
||||
optional: true
|
||||
"@ai-sdk/vercel":
|
||||
optional: true
|
||||
"@ai-sdk/xai":
|
||||
optional: true
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@cherrystudio/embedjs-interfaces@npm:0.1.30":
|
||||
version: 0.1.30
|
||||
resolution: "@cherrystudio/embedjs-interfaces@npm:0.1.30"
|
||||
@ -3184,6 +3590,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/api@npm:1.9.0":
|
||||
version: 1.9.0
|
||||
resolution: "@opentelemetry/api@npm:1.9.0"
|
||||
checksum: 10c0/9aae2fe6e8a3a3eeb6c1fdef78e1939cf05a0f37f8a4fae4d6bf2e09eb1e06f966ece85805626e01ba5fab48072b94f19b835449e58b6d26720ee19a58298add
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@parcel/watcher-android-arm64@npm:2.5.1":
|
||||
version: 2.5.1
|
||||
resolution: "@parcel/watcher-android-arm64@npm:2.5.1"
|
||||
@ -3815,6 +4228,94 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/eventstream-codec@npm:^4.0.1":
|
||||
version: 4.0.4
|
||||
resolution: "@smithy/eventstream-codec@npm:4.0.4"
|
||||
dependencies:
|
||||
"@aws-crypto/crc32": "npm:5.2.0"
|
||||
"@smithy/types": "npm:^4.3.1"
|
||||
"@smithy/util-hex-encoding": "npm:^4.0.0"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/89b76826d4d3bf97317e3539ece105b9a03552144ad816a687b0b2cbca60e2b3513062c04b6cfacaffb270d616ffc8ac8bf549afc4aa676a6d7465df5a3215ba
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/is-array-buffer@npm:^2.2.0":
|
||||
version: 2.2.0
|
||||
resolution: "@smithy/is-array-buffer@npm:2.2.0"
|
||||
dependencies:
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/2f2523cd8cc4538131e408eb31664983fecb0c8724956788b015aaf3ab85a0c976b50f4f09b176f1ed7bbe79f3edf80743be7a80a11f22cd9ce1285d77161aaf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/is-array-buffer@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@smithy/is-array-buffer@npm:4.0.0"
|
||||
dependencies:
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/ae393fbd5944d710443cd5dd225d1178ef7fb5d6259c14f3e1316ec75e401bda6cf86f7eb98bfd38e5ed76e664b810426a5756b916702cbd418f0933e15e7a3b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/types@npm:^4.3.1":
|
||||
version: 4.3.1
|
||||
resolution: "@smithy/types@npm:4.3.1"
|
||||
dependencies:
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/8b350562b9ed4ff97465025b4ae77a34bb07b9d47fb6f9781755aac9401b0355a63c2fef307393e2dae3fa0277149dd7d83f5bc2a63d4ad3519ea32fd56b5cda
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/util-buffer-from@npm:^2.2.0":
|
||||
version: 2.2.0
|
||||
resolution: "@smithy/util-buffer-from@npm:2.2.0"
|
||||
dependencies:
|
||||
"@smithy/is-array-buffer": "npm:^2.2.0"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/223d6a508b52ff236eea01cddc062b7652d859dd01d457a4e50365af3de1e24a05f756e19433f6ccf1538544076b4215469e21a4ea83dc1d58d829725b0dbc5a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/util-buffer-from@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@smithy/util-buffer-from@npm:4.0.0"
|
||||
dependencies:
|
||||
"@smithy/is-array-buffer": "npm:^4.0.0"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/be7cd33b6cb91503982b297716251e67cdca02819a15797632091cadab2dc0b4a147fff0709a0aa9bbc0b82a2644a7ed7c8afdd2194d5093cee2e9605b3a9f6f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/util-hex-encoding@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@smithy/util-hex-encoding@npm:4.0.0"
|
||||
dependencies:
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/70dbb3aa1a79aff3329d07a66411ff26398df338bdd8a6d077b438231afe3dc86d9a7022204baddecd8bc633f059d5c841fa916d81dd7447ea79b64148f386d2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/util-utf8@npm:^2.0.0":
|
||||
version: 2.3.0
|
||||
resolution: "@smithy/util-utf8@npm:2.3.0"
|
||||
dependencies:
|
||||
"@smithy/util-buffer-from": "npm:^2.2.0"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/e18840c58cc507ca57fdd624302aefd13337ee982754c9aa688463ffcae598c08461e8620e9852a424d662ffa948fc64919e852508028d09e89ced459bd506ab
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@smithy/util-utf8@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "@smithy/util-utf8@npm:4.0.0"
|
||||
dependencies:
|
||||
"@smithy/util-buffer-from": "npm:^4.0.0"
|
||||
tslib: "npm:^2.6.2"
|
||||
checksum: 10c0/28a5a5372cbf0b3d2e32dd16f79b04c2aec6f704cf13789db922e9686fde38dde0171491cfa4c2c201595d54752a319faaeeed3c325329610887694431e28c98
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@strongtz/win32-arm64-msvc@npm:^0.4.7":
|
||||
version: 0.4.7
|
||||
resolution: "@strongtz/win32-arm64-msvc@npm:0.4.7"
|
||||
@ -4394,6 +4895,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/diff-match-patch@npm:^1.0.36":
|
||||
version: 1.0.36
|
||||
resolution: "@types/diff-match-patch@npm:1.0.36"
|
||||
checksum: 10c0/0bad011ab138baa8bde94e7815064bb881f010452463272644ddbbb0590659cb93f7aa2776ff442c6721d70f202839e1053f8aa62d801cc4166f7a3ea9130055
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/diff@npm:^7":
|
||||
version: 7.0.2
|
||||
resolution: "@types/diff@npm:7.0.2"
|
||||
@ -5824,6 +6332,26 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ai@npm:^4.3.16":
|
||||
version: 4.3.16
|
||||
resolution: "ai@npm:4.3.16"
|
||||
dependencies:
|
||||
"@ai-sdk/provider": "npm:1.1.3"
|
||||
"@ai-sdk/provider-utils": "npm:2.2.8"
|
||||
"@ai-sdk/react": "npm:1.2.12"
|
||||
"@ai-sdk/ui-utils": "npm:1.2.11"
|
||||
"@opentelemetry/api": "npm:1.9.0"
|
||||
jsondiffpatch: "npm:0.6.0"
|
||||
peerDependencies:
|
||||
react: ^18 || ^19 || ^19.0.0-rc
|
||||
zod: ^3.23.8
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
checksum: 10c0/befe761c9386cda6de33370a2590900352b444d81959255c624e2bfd40765f126d29269f0ef3e00bde07daf237004aa0b66d0b253664aa478c148e923ce78c41
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ajv-formats@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "ajv-formats@npm:2.1.1"
|
||||
@ -6232,6 +6760,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"aws4fetch@npm:^1.0.20":
|
||||
version: 1.0.20
|
||||
resolution: "aws4fetch@npm:1.0.20"
|
||||
checksum: 10c0/a4eac7bd0d1c3e611c17ed1ef41ac0b48c0a8e74a985ad968c071e74d94586d3572edc943b43fa5ca756c686ea73baa2f48e264d657bb8c2e95c8e0037d48a87
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axios@npm:^1.7.3":
|
||||
version: 1.8.4
|
||||
resolution: "axios@npm:1.8.4"
|
||||
@ -6736,7 +7271,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"chalk@npm:^5.4.1":
|
||||
"chalk@npm:^5.3.0, chalk@npm:^5.4.1":
|
||||
version: 5.4.1
|
||||
resolution: "chalk@npm:5.4.1"
|
||||
checksum: 10c0/b23e88132c702f4855ca6d25cb5538b1114343e41472d5263ee8a37cccfccd9c4216d111e1097c6a27830407a1dc81fecdf2a56f2c63033d4dbbd88c10b0dcef
|
||||
@ -8169,6 +8704,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"diff-match-patch@npm:^1.0.5":
|
||||
version: 1.0.5
|
||||
resolution: "diff-match-patch@npm:1.0.5"
|
||||
checksum: 10c0/142b6fad627b9ef309d11bd935e82b84c814165a02500f046e2773f4ea894d10ed3017ac20454900d79d4a0322079f5b713cf0986aaf15fce0ec4a2479980c86
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"diff@npm:^7.0.0":
|
||||
version: 7.0.0
|
||||
resolution: "diff@npm:7.0.0"
|
||||
@ -10258,7 +10800,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"google-auth-library@npm:^9.14.2":
|
||||
"google-auth-library@npm:^9.14.2, google-auth-library@npm:^9.15.0":
|
||||
version: 9.15.1
|
||||
resolution: "google-auth-library@npm:9.15.1"
|
||||
dependencies:
|
||||
@ -11458,6 +12000,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"json-schema@npm:^0.4.0":
|
||||
version: 0.4.0
|
||||
resolution: "json-schema@npm:0.4.0"
|
||||
checksum: 10c0/d4a637ec1d83544857c1c163232f3da46912e971d5bf054ba44fdb88f07d8d359a462b4aec46f2745efbc57053365608d88bc1d7b1729f7b4fc3369765639ed3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"json-stable-stringify-without-jsonify@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "json-stable-stringify-without-jsonify@npm:1.0.1"
|
||||
@ -11490,6 +12039,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jsondiffpatch@npm:0.6.0":
|
||||
version: 0.6.0
|
||||
resolution: "jsondiffpatch@npm:0.6.0"
|
||||
dependencies:
|
||||
"@types/diff-match-patch": "npm:^1.0.36"
|
||||
chalk: "npm:^5.3.0"
|
||||
diff-match-patch: "npm:^1.0.5"
|
||||
bin:
|
||||
jsondiffpatch: bin/jsondiffpatch.js
|
||||
checksum: 10c0/f7822e48a8ef8b9f7c6024cc59b7d3707a9fe6d84fd776d169de5a1803ad551ffe7cfdc7587f3900f224bc70897355884ed43eb1c8ccd02e7f7b43a7ebcfed4f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jsonfile@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "jsonfile@npm:4.0.0"
|
||||
@ -16438,6 +17000,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"secure-json-parse@npm:^2.7.0":
|
||||
version: 2.7.0
|
||||
resolution: "secure-json-parse@npm:2.7.0"
|
||||
checksum: 10c0/f57eb6a44a38a3eeaf3548228585d769d788f59007454214fab9ed7f01fbf2e0f1929111da6db28cf0bcc1a2e89db5219a59e83eeaec3a54e413a0197ce879e4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"seek-bzip@npm:^1.0.5":
|
||||
version: 1.0.6
|
||||
resolution: "seek-bzip@npm:1.0.6"
|
||||
@ -17214,6 +17783,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"swr@npm:^2.2.5":
|
||||
version: 2.3.3
|
||||
resolution: "swr@npm:2.3.3"
|
||||
dependencies:
|
||||
dequal: "npm:^2.0.3"
|
||||
use-sync-external-store: "npm:^1.4.0"
|
||||
peerDependencies:
|
||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
checksum: 10c0/882fc8291912860e0c50eae3470ebf0cd58b0144cb12adcc4b14c5cef913ea06479043830508d8b0b3d4061d99ad8dd52485c9c879fbd4e9b893484e6d8da9e3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"symbol-tree@npm:^3.2.4":
|
||||
version: 3.2.4
|
||||
resolution: "symbol-tree@npm:3.2.4"
|
||||
@ -17361,6 +17942,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"throttleit@npm:2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "throttleit@npm:2.1.0"
|
||||
checksum: 10c0/1696ae849522cea6ba4f4f3beac1f6655d335e51b42d99215e196a718adced0069e48deaaf77f7e89f526ab31de5b5c91016027da182438e6f9280be2f3d5265
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"through2@npm:4.0.2":
|
||||
version: 4.0.2
|
||||
resolution: "through2@npm:4.0.2"
|
||||
@ -17673,7 +18261,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.8.1":
|
||||
"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.6.2, tslib@npm:^2.8.1":
|
||||
version: 2.8.1
|
||||
resolution: "tslib@npm:2.8.1"
|
||||
checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62
|
||||
@ -17753,7 +18341,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@npm:^5.4.3, typescript@npm:^5.6.2":
|
||||
"typescript@npm:^5.0.0, typescript@npm:^5.4.3, typescript@npm:^5.6.2":
|
||||
version: 5.8.3
|
||||
resolution: "typescript@npm:5.8.3"
|
||||
bin:
|
||||
@ -17763,7 +18351,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"typescript@patch:typescript@npm%3A^5.4.3#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.6.2#optional!builtin<compat/typescript>":
|
||||
"typescript@patch:typescript@npm%3A^5.0.0#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.4.3#optional!builtin<compat/typescript>, typescript@patch:typescript@npm%3A^5.6.2#optional!builtin<compat/typescript>":
|
||||
version: 5.8.3
|
||||
resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin<compat/typescript>::version=5.8.3&hash=5786d5"
|
||||
bin:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user