mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 14:41:24 +08:00
Compare commits
6 Commits
4b5653c98c
...
4769806b19
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4769806b19 | ||
|
|
a6ba5d34e0 | ||
|
|
eb2aaf1759 | ||
|
|
cc6fcda856 | ||
|
|
1ce2076185 | ||
|
|
a4eeb6c4b1 |
@ -134,38 +134,38 @@ artifactBuildCompleted: scripts/artifact-build-completed.js
|
||||
releaseInfo:
|
||||
releaseNotes: |
|
||||
<!--LANG:en-->
|
||||
Cherry Studio 1.7.5 - Filesystem MCP Overhaul & Topic Management
|
||||
Cherry Studio 1.7.6 - New Models & MCP Enhancements
|
||||
|
||||
This release features a completely rewritten filesystem MCP server, new batch topic management, and improved assistant management.
|
||||
This release adds support for new AI models and includes a new MCP server for memory management.
|
||||
|
||||
✨ New Features
|
||||
- [MCP] Rewrite filesystem MCP server with improved tool set (glob, ls, grep, read, write, edit, delete)
|
||||
- [Topics] Add topic manage mode for batch delete and move operations with search functionality
|
||||
- [Assistants] Merge import/subscribe popups and add export to assistant management
|
||||
- [Knowledge] Use prompt injection for forced knowledge base search (faster response times)
|
||||
- [Settings] Add tool use mode setting (prompt/function) to default assistant settings
|
||||
- [Models] Add support for Xiaomi MiMo model
|
||||
- [Models] Add support for Gemini 3 Flash and Pro model detection
|
||||
- [Models] Add support for Volcengine Doubao-Seed-1.8 model
|
||||
- [MCP] Add Nowledge Mem builtin MCP server for memory management
|
||||
- [Settings] Add default reasoning effort option to resolve confusion between undefined and none
|
||||
|
||||
🐛 Bug Fixes
|
||||
- [Model] Correct typo in Gemini 3 Pro Image Preview model name
|
||||
- [Installer] Auto-install VC++ Redistributable without user prompt
|
||||
- [Notes] Fix notes directory validation and default path reset for cross-platform restore
|
||||
- [OAuth] Bind OAuth callback server to localhost (127.0.0.1) for security
|
||||
- [Azure] Restore deployment-based URLs for non-v1 apiVersion
|
||||
- [Translation] Disable reasoning mode for translation to improve efficiency
|
||||
- [Image] Update API path for image generation requests in OpenAIBaseClient
|
||||
- [Windows] Auto-discover and persist Git Bash path on Windows for scoop users
|
||||
|
||||
<!--LANG:zh-CN-->
|
||||
Cherry Studio 1.7.5 - 文件系统 MCP 重构与话题管理
|
||||
Cherry Studio 1.7.6 - 新模型与 MCP 增强
|
||||
|
||||
本次更新完全重写了文件系统 MCP 服务器,新增批量话题管理功能,并改进了助手管理。
|
||||
本次更新添加了多个新 AI 模型支持,并新增记忆管理 MCP 服务器。
|
||||
|
||||
✨ 新功能
|
||||
- [MCP] 重写文件系统 MCP 服务器,提供改进的工具集(glob、ls、grep、read、write、edit、delete)
|
||||
- [话题] 新增话题管理模式,支持批量删除和移动操作,带搜索功能
|
||||
- [助手] 合并导入/订阅弹窗,并在助手管理中添加导出功能
|
||||
- [知识库] 使用提示词注入进行强制知识库搜索(响应更快)
|
||||
- [设置] 在默认助手设置中添加工具使用模式设置(prompt/function)
|
||||
- [模型] 添加小米 MiMo 模型支持
|
||||
- [模型] 添加 Gemini 3 Flash 和 Pro 模型检测支持
|
||||
- [模型] 添加火山引擎 Doubao-Seed-1.8 模型支持
|
||||
- [MCP] 新增 Nowledge Mem 内置 MCP 服务器,用于记忆管理
|
||||
- [设置] 添加默认推理强度选项,解决 undefined 和 none 之间的混淆
|
||||
|
||||
🐛 问题修复
|
||||
- [模型] 修正 Gemini 3 Pro Image Preview 模型名称的拼写错误
|
||||
- [安装程序] 自动安装 VC++ 运行库,无需用户确认
|
||||
- [笔记] 修复跨平台恢复场景下的笔记目录验证和默认路径重置逻辑
|
||||
- [OAuth] 将 OAuth 回调服务器绑定到 localhost (127.0.0.1) 以提高安全性
|
||||
- [Azure] 修复非 v1 apiVersion 的部署 URL 问题
|
||||
- [翻译] 禁用翻译时的推理模式以提高效率
|
||||
- [图像] 更新 OpenAIBaseClient 中图像生成请求的 API 路径
|
||||
- [Windows] 自动发现并保存 Windows scoop 用户的 Git Bash 路径
|
||||
<!--LANG:END-->
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "CherryStudio",
|
||||
"version": "1.7.5",
|
||||
"version": "1.7.6",
|
||||
"private": true,
|
||||
"description": "A powerful AI assistant for producer.",
|
||||
"main": "./out/main/index.js",
|
||||
|
||||
@ -120,6 +120,23 @@ export class AiSdkToChunkAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果有累积的思考内容,发送 THINKING_COMPLETE chunk 并清空
|
||||
* @param final 包含 reasoningContent 的状态对象
|
||||
* @returns 是否发送了 THINKING_COMPLETE chunk
|
||||
*/
|
||||
private emitThinkingCompleteIfNeeded(final: { reasoningContent: string; [key: string]: any }): boolean {
|
||||
if (final.reasoningContent) {
|
||||
this.onChunk({
|
||||
type: ChunkType.THINKING_COMPLETE,
|
||||
text: final.reasoningContent
|
||||
})
|
||||
final.reasoningContent = ''
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换 AI SDK chunk 为 Cherry Studio chunk 并调用回调
|
||||
* @param chunk AI SDK 的 chunk 数据
|
||||
@ -145,6 +162,9 @@ export class AiSdkToChunkAdapter {
|
||||
}
|
||||
// === 文本相关事件 ===
|
||||
case 'text-start':
|
||||
// 如果有未完成的思考内容,先生成 THINKING_COMPLETE
|
||||
// 这处理了某些提供商不发送 reasoning-end 事件的情况
|
||||
this.emitThinkingCompleteIfNeeded(final)
|
||||
this.onChunk({
|
||||
type: ChunkType.TEXT_START
|
||||
})
|
||||
@ -215,11 +235,7 @@ export class AiSdkToChunkAdapter {
|
||||
})
|
||||
break
|
||||
case 'reasoning-end':
|
||||
this.onChunk({
|
||||
type: ChunkType.THINKING_COMPLETE,
|
||||
text: final.reasoningContent || ''
|
||||
})
|
||||
final.reasoningContent = ''
|
||||
this.emitThinkingCompleteIfNeeded(final)
|
||||
break
|
||||
|
||||
// === 工具调用相关事件(原始 AI SDK 事件,如果没有被中间件处理) ===
|
||||
|
||||
@ -29,10 +29,20 @@ interface BaseCallbacksDependencies {
|
||||
assistantMsgId: string
|
||||
saveUpdatesToDB: any
|
||||
assistant: Assistant
|
||||
getCurrentThinkingInfo?: () => { blockId: string | null; millsec: number }
|
||||
}
|
||||
|
||||
export const createBaseCallbacks = (deps: BaseCallbacksDependencies) => {
|
||||
const { blockManager, dispatch, getState, topicId, assistantMsgId, saveUpdatesToDB, assistant } = deps
|
||||
const {
|
||||
blockManager,
|
||||
dispatch,
|
||||
getState,
|
||||
topicId,
|
||||
assistantMsgId,
|
||||
saveUpdatesToDB,
|
||||
assistant,
|
||||
getCurrentThinkingInfo
|
||||
} = deps
|
||||
|
||||
const startTime = Date.now()
|
||||
const notificationService = NotificationService.getInstance()
|
||||
@ -98,10 +108,17 @@ export const createBaseCallbacks = (deps: BaseCallbacksDependencies) => {
|
||||
const possibleBlockId = findBlockIdForCompletion()
|
||||
|
||||
if (possibleBlockId) {
|
||||
// 更改上一个block的状态为ERROR
|
||||
const changes = {
|
||||
// 更改上一个block的状态为ERROR/PAUSED
|
||||
const changes: Record<string, any> = {
|
||||
status: isErrorTypeAbort ? MessageBlockStatus.PAUSED : MessageBlockStatus.ERROR
|
||||
}
|
||||
// 如果是 thinking block,保留实际思考时间
|
||||
if (blockManager.lastBlockType === MessageBlockType.THINKING) {
|
||||
const thinkingInfo = getCurrentThinkingInfo?.()
|
||||
if (thinkingInfo?.blockId === possibleBlockId && thinkingInfo?.millsec && thinkingInfo.millsec > 0) {
|
||||
changes.thinking_millsec = thinkingInfo.millsec
|
||||
}
|
||||
}
|
||||
blockManager.smartBlockUpdate(possibleBlockId, changes, blockManager.lastBlockType!, true)
|
||||
}
|
||||
|
||||
@ -111,13 +128,28 @@ export const createBaseCallbacks = (deps: BaseCallbacksDependencies) => {
|
||||
if (currentMessage) {
|
||||
const allBlockRefs = findAllBlocks(currentMessage)
|
||||
const blockState = getState().messageBlocks
|
||||
// 获取当前思考信息(如果有),用于保留实际思考时间
|
||||
const thinkingInfo = getCurrentThinkingInfo?.()
|
||||
for (const blockRef of allBlockRefs) {
|
||||
const block = blockState.entities[blockRef.id]
|
||||
if (block && block.status === MessageBlockStatus.STREAMING && block.id !== possibleBlockId) {
|
||||
// 构建更新对象
|
||||
const changes: Record<string, any> = {
|
||||
status: isErrorTypeAbort ? MessageBlockStatus.PAUSED : MessageBlockStatus.ERROR
|
||||
}
|
||||
// 如果是 thinking block 且有思考时间信息,保留实际思考时间
|
||||
if (
|
||||
block.type === MessageBlockType.THINKING &&
|
||||
thinkingInfo?.blockId === block.id &&
|
||||
thinkingInfo?.millsec &&
|
||||
thinkingInfo.millsec > 0
|
||||
) {
|
||||
changes.thinking_millsec = thinkingInfo.millsec
|
||||
}
|
||||
dispatch(
|
||||
updateOneBlock({
|
||||
id: block.id,
|
||||
changes: { status: isErrorTypeAbort ? MessageBlockStatus.PAUSED : MessageBlockStatus.ERROR }
|
||||
changes
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@ -23,6 +23,12 @@ interface CallbacksDependencies {
|
||||
export const createCallbacks = (deps: CallbacksDependencies) => {
|
||||
const { blockManager, dispatch, getState, topicId, assistantMsgId, saveUpdatesToDB, assistant } = deps
|
||||
|
||||
// 首先创建 thinkingCallbacks ,以便传递 getCurrentThinkingInfo 给 baseCallbacks
|
||||
const thinkingCallbacks = createThinkingCallbacks({
|
||||
blockManager,
|
||||
assistantMsgId
|
||||
})
|
||||
|
||||
// 创建基础回调
|
||||
const baseCallbacks = createBaseCallbacks({
|
||||
blockManager,
|
||||
@ -31,13 +37,8 @@ export const createCallbacks = (deps: CallbacksDependencies) => {
|
||||
topicId,
|
||||
assistantMsgId,
|
||||
saveUpdatesToDB,
|
||||
assistant
|
||||
})
|
||||
|
||||
// 创建各类回调
|
||||
const thinkingCallbacks = createThinkingCallbacks({
|
||||
blockManager,
|
||||
assistantMsgId
|
||||
assistant,
|
||||
getCurrentThinkingInfo: thinkingCallbacks.getCurrentThinkingInfo
|
||||
})
|
||||
|
||||
const toolCallbacks = createToolCallbacks({
|
||||
|
||||
@ -19,6 +19,12 @@ export const createThinkingCallbacks = (deps: ThinkingCallbacksDependencies) =>
|
||||
let thinking_millsec_now: number = 0
|
||||
|
||||
return {
|
||||
// 获取当前思考时间(用于停止回复时保留思考时间)
|
||||
getCurrentThinkingInfo: () => ({
|
||||
blockId: thinkingBlockId,
|
||||
millsec: thinking_millsec_now > 0 ? performance.now() - thinking_millsec_now : 0
|
||||
}),
|
||||
|
||||
onThinkingStart: async () => {
|
||||
if (blockManager.hasInitialPlaceholder) {
|
||||
const changes: Partial<MessageBlock> = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user