chore: update release notes and version to 1.6.0-beta.6

- Refined performance optimizations for AI services and improved compatibility with various providers.
- Enhanced error handling and stability in the ModernAiProvider class.
- Updated version in package.json to 1.6.0-beta.6.
This commit is contained in:
MyPrototypeWhat 2025-09-03 17:10:41 +08:00
parent 976d246cac
commit 01c4777691
5 changed files with 62 additions and 40 deletions

View File

@ -121,26 +121,12 @@ afterSign: scripts/notarize.js
artifactBuildCompleted: scripts/artifact-build-completed.js
releaseInfo:
releaseNotes: |
✨ 重要更新:
- 增强Web搜索功能重构搜索结果处理和展示逻辑
- 优化知识库设置:默认关闭知识识别以提升性能
- 新增Gemini 2.5 Flash Image模型的自动图像生成功能
- 支持链接OG数据解析和预览展示
- 增强OCR服务的Linux兼容性
🔧 性能优化:
- 重构AI核心架构采用现代化的AI SDK 5.0
- 优化消息重试机制,新增"重试失败消息"按钮
- 改进侧边栏动画效果和用户交互体验
- 优化Vite构建系统使用Rolldown引擎提升构建性能
- 重构参数处理和文件处理模块
- 优化API key轮转机制
- 优化AI服务连接方式提升响应速度和稳定性
- 改进模型列表获取功能,减少不必要的网络请求
- 增强各AI服务商的兼容性和连接可靠性
🐛 修复问题:
- 修复tabs组件高度不足导致边框样式问题
- 修复Gemini 2.5 Flash Image模型的图像生成按钮状态
- 修复ModelScope DeepSeek v3.1思考模式问题
- 修复PoeLogo在provider UI组件中的渲染问题
- 修复ASAR集成相关问题
- 移除加载状态阻塞输入的问题
- 修复多个UI组件和样式问题
🐛 问题修复:
- 修复部分AI服务商连接失败的问题
- 修复模型配置加载时的潜在错误
- 提升应用整体稳定性和容错能力

View File

@ -1,6 +1,6 @@
{
"name": "CherryStudio",
"version": "1.6.0-beta.5",
"version": "1.6.0-beta.6",
"private": true,
"description": "A powerful AI assistant for producer.",
"main": "./out/main/index.js",

View File

@ -42,18 +42,36 @@ export type ModernAiProviderConfig = AiSdkMiddlewareConfig & {
export default class ModernAiProvider {
private legacyProvider: LegacyAiProvider
private config: ReturnType<typeof providerToAiSdkConfig>
private config?: ReturnType<typeof providerToAiSdkConfig>
private actualProvider: Provider
private model: Model
private model?: Model
private localProvider: Awaited<AiSdkProvider> | null = null
constructor(model: Model, provider?: Provider) {
this.actualProvider = provider || getActualProvider(model)
this.legacyProvider = new LegacyAiProvider(this.actualProvider)
this.model = model
// 构造函数重载签名
constructor(model: Model, provider?: Provider)
constructor(provider: Provider)
constructor(modelOrProvider: Model | Provider, provider?: Provider)
constructor(modelOrProvider: Model | Provider, provider?: Provider) {
if (this.isModel(modelOrProvider)) {
// 传入的是 Model
this.model = modelOrProvider
this.actualProvider = provider || getActualProvider(modelOrProvider)
// 只保存配置不预先创建executor
this.config = providerToAiSdkConfig(this.actualProvider, modelOrProvider)
} else {
// 传入的是 Provider
this.actualProvider = modelOrProvider
// model为可选某些操作如fetchModels不需要model
}
// 只保存配置不预先创建executor
this.config = providerToAiSdkConfig(this.actualProvider, model)
this.legacyProvider = new LegacyAiProvider(this.actualProvider)
}
/**
* provider Model Provider
*/
private isModel(obj: Model | Provider): obj is Model {
return 'provider' in obj && typeof obj.provider === 'string'
}
public getActualProvider() {
@ -61,6 +79,16 @@ export default class ModernAiProvider {
}
public async completions(modelId: string, params: StreamTextParams, config: ModernAiProviderConfig) {
// 检查model是否存在
if (!this.model) {
throw new Error('Model is required for completions. Please use constructor with model parameter.')
}
// 确保配置存在
if (!this.config) {
this.config = providerToAiSdkConfig(this.actualProvider, this.model)
}
// 准备特殊配置
await prepareSpecialProviderConfig(this.actualProvider, this.config)
@ -127,7 +155,7 @@ export default class ModernAiProvider {
params: StreamTextParams,
config: ModernAiProviderConfig & { topicId: string }
): Promise<CompletionsResult> {
const modelId = this.model.id
const modelId = this.model!.id
const traceName = `${this.actualProvider.name}.${modelId}.${config.callType}`
const traceParams: StartSpanParams = {
name: traceName,
@ -211,10 +239,10 @@ export default class ModernAiProvider {
params: StreamTextParams,
config: ModernAiProviderConfig
): Promise<CompletionsResult> {
const modelId = this.model.id
const modelId = this.model!.id
logger.info('Starting modernCompletions', {
modelId,
providerId: this.config.providerId,
providerId: this.config!.providerId,
topicId: config.topicId,
hasOnChunk: !!config.onChunk,
hasTools: !!params.tools && Object.keys(params.tools).length > 0,
@ -225,11 +253,11 @@ export default class ModernAiProvider {
const plugins = buildPlugins(config)
// 用构建好的插件数组创建executor
const executor = createExecutor(this.config.providerId, this.config.options, plugins)
const executor = createExecutor(this.config!.providerId, this.config!.options, plugins)
// 创建带有中间件的执行器
if (config.onChunk) {
const accumulate = this.model.supported_text_delta !== false // true and undefined
const accumulate = this.model!.supported_text_delta !== false // true and undefined
const adapter = new AiSdkToChunkAdapter(config.onChunk, config.mcpTools, accumulate)
const streamResult = await executor.streamText({
@ -308,7 +336,7 @@ export default class ModernAiProvider {
}
// 调用新 AI SDK 的图像生成功能
const executor = createExecutor(this.config.providerId, this.config.options, [])
const executor = createExecutor(this.config!.providerId, this.config!.options, [])
const result = await executor.generateImage({
model,
...imageParams
@ -428,7 +456,7 @@ export default class ModernAiProvider {
...(signal && { abortSignal: signal })
}
const executor = createExecutor(this.config.providerId, this.config.options, [])
const executor = createExecutor(this.config!.providerId, this.config!.options, [])
const result = await executor.generateImage({
model: this.localProvider?.imageModel(model) as ImageModel,
...aiSdkParams

View File

@ -131,12 +131,21 @@ export function providerToAiSdkConfig(
// 添加额外headers
if (actualProvider.extra_headers) {
extraOptions.headers = actualProvider.extra_headers
// copy from openaiBaseClient/openaiResponseApiClient
if (aiSdkProviderId === 'openai') {
extraOptions.headers = {
...extraOptions.headers,
'HTTP-Referer': 'https://cherry-ai.com',
'X-Title': 'Cherry Studio',
'X-Api-Key': baseConfig.apiKey
}
}
}
// copilot
if (actualProvider.id === 'copilot') {
extraOptions.headers = {
...extraOptions.extra_headers,
...extraOptions.headers,
'editor-version': 'vscode/1.97.2',
'copilot-vision-request': 'true'
}
@ -183,7 +192,6 @@ export function providerToAiSdkConfig(
} else if (baseConfig.baseURL.endsWith('/v1')) {
baseConfig.baseURL = baseConfig.baseURL.slice(0, -3)
}
baseConfig.baseURL = isEmpty(baseConfig.baseURL) ? '' : baseConfig.baseURL
}

View File

@ -350,7 +350,7 @@ export function hasApiKey(provider: Provider) {
// }
export async function fetchModels(provider: Provider): Promise<SdkModel[]> {
const AI = new AiProviderNew({} as Model, provider)
const AI = new AiProviderNew(provider)
try {
return await AI.models()