refactor: update preference management in AI components

- Replaced instances of useSettings with usePreference for better preference handling across various components.
- Updated function signatures to support async operations where necessary.
- Adjusted imports to utilize shared configuration for prompts, enhancing consistency in prompt management.
- Improved error handling and logging in AI-related functionalities.
This commit is contained in:
fullex 2025-09-06 18:21:11 +08:00
parent 2931e558b3
commit 9da3e82c47
13 changed files with 31 additions and 33 deletions

View File

@ -8,8 +8,8 @@
*/
import { createExecutor } from '@cherrystudio/ai-core'
import { preferenceService } from '@data/PreferenceService'
import { loggerService } from '@logger'
import { getEnableDeveloperMode } from '@renderer/hooks/useSettings'
import { addSpan, endSpan } from '@renderer/services/SpanManagerService'
import { StartSpanParams } from '@renderer/trace/types/ModelSpanEntity'
import type { Assistant, GenerateImageParams, Model, Provider } from '@renderer/types'
@ -131,7 +131,7 @@ export default class ModernAiProvider {
}
}
if (config.topicId && getEnableDeveloperMode()) {
if (config.topicId && (await preferenceService.get('app.developer_mode.enabled'))) {
// TypeScript类型窄化确保topicId是string类型
const traceConfig = {
...config,
@ -200,7 +200,7 @@ export default class ModernAiProvider {
isImageGeneration: config.isImageGenerationEndpoint
})
const span = addSpan(traceParams)
const span = await addSpan(traceParams)
if (!span) {
logger.warn('Failed to create span, falling back to regular completions', {
topicId: config.topicId,
@ -276,7 +276,7 @@ export default class ModernAiProvider {
})
// 根据条件构建插件数组
const plugins = buildPlugins(config)
const plugins = await buildPlugins(config)
// 用构建好的插件数组创建executor
const executor = createExecutor(this.config!.providerId, this.config!.options, plugins)

View File

@ -1,8 +1,8 @@
import { AiPlugin } from '@cherrystudio/ai-core'
import { createPromptToolUsePlugin, webSearchPlugin } from '@cherrystudio/ai-core/built-in/plugins'
import { preferenceService } from '@data/PreferenceService'
import { loggerService } from '@logger'
import { getEnableDeveloperMode } from '@renderer/hooks/useSettings'
import { Assistant } from '@renderer/types'
import type { Assistant } from '@renderer/types'
import { AiSdkMiddlewareConfig } from '../middleware/AiSdkMiddlewareBuilder'
import reasoningTimePlugin from './reasoningTimePlugin'
@ -13,12 +13,12 @@ const logger = loggerService.withContext('PluginBuilder')
/**
*
*/
export function buildPlugins(
export async function buildPlugins(
middlewareConfig: AiSdkMiddlewareConfig & { assistant: Assistant; topicId?: string }
): AiPlugin[] {
): Promise<AiPlugin[]> {
const plugins: AiPlugin[] = []
if (middlewareConfig.topicId && getEnableDeveloperMode()) {
if (middlewareConfig.topicId && (await preferenceService.get('app.developer_mode.enabled'))) {
// 0. 添加 telemetry 插件
plugins.push(
createTelemetryPlugin({

View File

@ -8,17 +8,17 @@
*/
import { type AiRequestContext, definePlugin } from '@cherrystudio/ai-core'
import { loggerService } from '@logger'
// import { generateObject } from '@cherrystudio/ai-core'
import {
SEARCH_SUMMARY_PROMPT,
SEARCH_SUMMARY_PROMPT_KNOWLEDGE_ONLY,
SEARCH_SUMMARY_PROMPT_WEB_ONLY
} from '@renderer/config/prompts'
import { getDefaultModel, getProviderByModel } from '@renderer/services/AssistantService'
import store from '@renderer/store'
import { selectCurrentUserId, selectGlobalMemoryEnabled, selectMemoryConfig } from '@renderer/store/memory'
import type { Assistant } from '@renderer/types'
import { extractInfoFromXML, ExtractResults } from '@renderer/utils/extract'
// import { generateObject } from '@cherrystudio/ai-core'
import {
SEARCH_SUMMARY_PROMPT,
SEARCH_SUMMARY_PROMPT_KNOWLEDGE_ONLY,
SEARCH_SUMMARY_PROMPT_WEB_ONLY
} from '@shared/config/prompts'
import type { ModelMessage } from 'ai'
import { isEmpty } from 'lodash'

View File

@ -1,7 +1,7 @@
import { REFERENCE_PROMPT } from '@renderer/config/prompts'
import { processKnowledgeSearch } from '@renderer/services/KnowledgeService'
import type { Assistant, KnowledgeReference } from '@renderer/types'
import { ExtractResults, KnowledgeExtractResults } from '@renderer/utils/extract'
import { REFERENCE_PROMPT } from '@shared/config/prompts'
import { type InferToolInput, type InferToolOutput, tool } from 'ai'
import { isEmpty } from 'lodash'
import { z } from 'zod'

View File

@ -1,7 +1,7 @@
import { REFERENCE_PROMPT } from '@renderer/config/prompts'
import WebSearchService from '@renderer/services/WebSearchService'
import { WebSearchProvider, WebSearchProviderResponse } from '@renderer/types'
import { ExtractResults } from '@renderer/utils/extract'
import { REFERENCE_PROMPT } from '@shared/config/prompts'
import { type InferToolInput, type InferToolOutput, tool } from 'ai'
import { z } from 'zod'

View File

@ -1,6 +1,6 @@
import { isOpenAIWebSearchChatCompletionOnlyModel } from '@renderer/config/models'
import { WEB_SEARCH_PROMPT_FOR_OPENROUTER } from '@renderer/config/prompts'
import { Model } from '@renderer/types'
import { WEB_SEARCH_PROMPT_FOR_OPENROUTER } from '@shared/config/prompts'
export function getWebSearchParams(model: Model): Record<string, any> {
if (model.provider === 'hunyuan') {

View File

@ -1,6 +1,6 @@
import MinappPopupContainer from '@renderer/components/MinApp/MinappPopupContainer'
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
import { useRuntime } from '@renderer/hooks/useRuntime'
import { useNavbarPosition } from '@renderer/hooks/useSettings'
const TopViewMinappContainer = () => {
const { openedKeepAliveMinapps, openedOneOffMinapp } = useRuntime()

View File

@ -1,8 +1,8 @@
import { Model } from '@renderer/types'
import { getLowerBaseModelName } from '@renderer/utils'
import { WEB_SEARCH_PROMPT_FOR_OPENROUTER } from '@shared/config/prompts'
import OpenAI from 'openai'
import { WEB_SEARCH_PROMPT_FOR_OPENROUTER } from '../prompts'
import { getWebSearchTools } from '../tools'
import { isOpenAIReasoningModel } from './reasoning'
import { isGenerateImageModel, isVisionModel } from './vision'

View File

@ -11,7 +11,6 @@ import { useMessageEditing } from '@renderer/context/MessageEditingContext'
import { useChatContext } from '@renderer/hooks/useChatContext'
import { useMessageOperations } from '@renderer/hooks/useMessageOperations'
import { useNotesSettings } from '@renderer/hooks/useNotesSettings'
import { useMessageStyle } from '@renderer/hooks/useSettings'
import { useTemporaryValue } from '@renderer/hooks/useTemporaryValue'
import useTranslate from '@renderer/hooks/useTranslate'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
@ -111,11 +110,13 @@ const MessageMenubar: FC<Props> = (props) => {
removeMessageBlock
} = useMessageOperations(topic)
const { isBubbleStyle } = useMessageStyle()
const [messageStyle] = usePreference('chat.message.style')
const [enableDeveloperMode] = usePreference('app.developer_mode.enabled')
const [confirmDeleteMessage] = usePreference('chat.message.confirm_delete')
const [confirmRegenerateMessage] = usePreference('chat.message.confirm_regenerate')
const isBubbleStyle = messageStyle === 'bubble'
// const loading = useTopicLoading(topic)
const isUserMessage = message.role === 'user'
@ -644,7 +645,7 @@ const MessageMenubar: FC<Props> = (props) => {
onClick={async (e) => {
e.stopPropagation()
const title = await getMessageTitle(message)
const markdown = messageToMarkdown(message)
const markdown = await messageToMarkdown(message)
exportMessageToNotes(title, markdown, notesPath)
}}
$softHoverBg={softHoverBg}>

View File

@ -2,8 +2,8 @@ import { loggerService } from '@logger'
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
import { useMinappPopup } from '@renderer/hooks/useMinappPopup'
import { useMinapps } from '@renderer/hooks/useMinapps'
import { useNavbarPosition } from '@renderer/hooks/useNavbar'
import { useRuntime } from '@renderer/hooks/useRuntime'
import { useNavbarPosition } from '@renderer/hooks/useSettings'
import TabsService from '@renderer/services/TabsService'
import { FC, useEffect, useMemo, useRef } from 'react'
import { useNavigate, useParams } from 'react-router-dom'

View File

@ -8,11 +8,9 @@ import {
PushpinOutlined,
ReloadOutlined
} from '@ant-design/icons'
import { usePreference } from '@data/hooks/usePreference'
import { DEFAULT_MIN_APPS } from '@renderer/config/minapps'
import { useMinapps } from '@renderer/hooks/useMinapps'
import { useSettings } from '@renderer/hooks/useSettings'
import { useAppDispatch } from '@renderer/store'
import { setMinappsOpenLinkExternal } from '@renderer/store/settings'
import { MinAppType } from '@renderer/types'
import { Tooltip } from 'antd'
import { WebviewTag } from 'electron'
@ -32,8 +30,7 @@ interface Props {
const MinimalToolbar: FC<Props> = ({ app, webviewRef, currentUrl, onReload, onOpenDevTools }) => {
const { t } = useTranslation()
const { pinned, updatePinnedMinapps } = useMinapps()
const { minappsOpenLinkExternal } = useSettings()
const dispatch = useAppDispatch()
const [minappsOpenLinkExternal, setMinappsOpenLinkExternal] = usePreference('feature.minapp.open_link_external')
const navigate = useNavigate()
const [canGoBack, setCanGoBack] = useState(false)
const [canGoForward, setCanGoForward] = useState(false)
@ -75,8 +72,8 @@ const MinimalToolbar: FC<Props> = ({ app, webviewRef, currentUrl, onReload, onOp
}, [app, isPinned, pinned, updatePinnedMinapps])
const handleToggleOpenExternal = useCallback(() => {
dispatch(setMinappsOpenLinkExternal(!minappsOpenLinkExternal))
}, [dispatch, minappsOpenLinkExternal])
setMinappsOpenLinkExternal(!minappsOpenLinkExternal)
}, [setMinappsOpenLinkExternal, minappsOpenLinkExternal])
const handleOpenLink = useCallback(() => {
const urlToOpen = currentUrl || app.url

View File

@ -98,7 +98,7 @@ vi.mock('@renderer/utils', () => ({
getLowerBaseModelName: vi.fn((name) => name.toLowerCase())
}))
vi.mock('@renderer/config/prompts', () => ({
vi.mock('@shared/config/prompts', () => ({
WEB_SEARCH_PROMPT_FOR_OPENROUTER: 'mock-prompt'
}))

View File

@ -1,6 +1,6 @@
import { loggerService } from '@logger'
import { isQwenMTModel } from '@renderer/config/models'
import { LANG_DETECT_PROMPT } from '@renderer/config/prompts'
import { LANG_DETECT_PROMPT } from '@shared/config/prompts'
import { builtinLanguages as builtinLanguages, LanguagesEnum, UNKNOWN } from '@renderer/config/translate'
import db from '@renderer/databases'
import i18n from '@renderer/i18n'