mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-30 15:59:09 +08:00
refactor: replace keyv with cacheService
This commit is contained in:
parent
8a9b633af2
commit
f6ff436294
@ -140,7 +140,6 @@
|
||||
"@google/genai": "patch:@google/genai@npm%3A1.0.1#~/.yarn/patches/@google-genai-npm-1.0.1-e26f0f9af7.patch",
|
||||
"@hello-pangea/dnd": "^18.0.1",
|
||||
"@heroui/react": "^2.8.3",
|
||||
"@kangfenmao/keyv-storage": "^0.1.0",
|
||||
"@langchain/community": "^0.3.50",
|
||||
"@mistralai/mistralai": "^1.7.5",
|
||||
"@modelcontextprotocol/sdk": "^1.17.5",
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import { loggerService } from '@logger'
|
||||
import {
|
||||
isFunctionCallingModel,
|
||||
@ -53,7 +54,6 @@ import { isEmpty } from 'lodash'
|
||||
|
||||
import type { CompletionsContext } from '../middleware/types'
|
||||
import type { ApiClient, RequestTransformer, ResponseChunkTransformer } from './types'
|
||||
|
||||
const logger = loggerService.withContext('BaseApiClient')
|
||||
|
||||
/**
|
||||
@ -166,16 +166,16 @@ export abstract class BaseApiClient<
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const lastUsedKey = window.keyv.get(keyName)
|
||||
if (!lastUsedKey) {
|
||||
window.keyv.set(keyName, keys[0])
|
||||
const lastUsedKey = cacheService.getShared(keyName) as string | undefined
|
||||
if (lastUsedKey === undefined) {
|
||||
cacheService.setShared(keyName, keys[0])
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const currentIndex = keys.indexOf(lastUsedKey)
|
||||
const nextIndex = (currentIndex + 1) % keys.length
|
||||
const nextKey = keys[nextIndex]
|
||||
window.keyv.set(keyName, nextKey)
|
||||
cacheService.setShared(keyName, nextKey)
|
||||
|
||||
return nextKey
|
||||
}
|
||||
@ -331,7 +331,7 @@ export abstract class BaseApiClient<
|
||||
}
|
||||
|
||||
private getMemoryReferencesFromCache(message: Message) {
|
||||
const memories = window.keyv.get(`memory-search-${message.id}`) as MemoryItem[] | undefined
|
||||
const memories = cacheService.get(`memory-search-${message.id}`) as MemoryItem[] | undefined
|
||||
if (memories) {
|
||||
const memoryReferences: KnowledgeReference[] = memories.map((mem, index) => ({
|
||||
id: index + 1,
|
||||
@ -349,10 +349,10 @@ export abstract class BaseApiClient<
|
||||
if (isEmpty(content)) {
|
||||
return []
|
||||
}
|
||||
const webSearch: WebSearchResponse = window.keyv.get(`web-search-${message.id}`)
|
||||
const webSearch: WebSearchResponse | undefined = cacheService.get(`web-search-${message.id}`)
|
||||
|
||||
if (webSearch) {
|
||||
window.keyv.remove(`web-search-${message.id}`)
|
||||
cacheService.delete(`web-search-${message.id}`)
|
||||
return (webSearch.results as WebSearchProviderResponse).results.map(
|
||||
(result, index) =>
|
||||
({
|
||||
@ -375,10 +375,10 @@ export abstract class BaseApiClient<
|
||||
if (isEmpty(content)) {
|
||||
return []
|
||||
}
|
||||
const knowledgeReferences: KnowledgeReference[] = window.keyv.get(`knowledge-search-${message.id}`)
|
||||
const knowledgeReferences: KnowledgeReference[] | undefined = cacheService.get(`knowledge-search-${message.id}`)
|
||||
|
||||
if (!isEmpty(knowledgeReferences)) {
|
||||
window.keyv.remove(`knowledge-search-${message.id}`)
|
||||
if (knowledgeReferences && !isEmpty(knowledgeReferences)) {
|
||||
cacheService.delete(`knowledge-search-${message.id}`)
|
||||
logger.debug(`Found ${knowledgeReferences.length} knowledge base references in cache for ID: ${message.id}`)
|
||||
return knowledgeReferences
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
type ProviderId,
|
||||
type ProviderSettingsMap
|
||||
} from '@cherrystudio/ai-core/provider'
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import { isOpenAIChatCompletionOnlyModel } from '@renderer/config/models'
|
||||
import { isNewApiProvider } from '@renderer/config/providers'
|
||||
import {
|
||||
@ -22,7 +23,6 @@ import { cloneDeep, isEmpty } from 'lodash'
|
||||
|
||||
import { aihubmixProviderCreator, newApiResolverCreator, vertexAnthropicProviderCreator } from './config'
|
||||
import { getAiSdkProviderId } from './factory'
|
||||
|
||||
const logger = loggerService.withContext('ProviderConfigProcessor')
|
||||
|
||||
/**
|
||||
@ -37,16 +37,16 @@ function getRotatedApiKey(provider: Provider): string {
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const lastUsedKey = window.keyv.get(keyName)
|
||||
if (!lastUsedKey) {
|
||||
window.keyv.set(keyName, keys[0])
|
||||
const lastUsedKey = cacheService.getShared(keyName) as string | undefined
|
||||
if (lastUsedKey === undefined) {
|
||||
cacheService.setShared(keyName, keys[0])
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const currentIndex = keys.indexOf(lastUsedKey)
|
||||
const nextIndex = (currentIndex + 1) % keys.length
|
||||
const nextKey = keys[nextIndex]
|
||||
window.keyv.set(keyName, nextKey)
|
||||
cacheService.setShared(keyName, nextKey)
|
||||
|
||||
return nextKey
|
||||
}
|
||||
|
||||
2
src/renderer/src/env.d.ts
vendored
2
src/renderer/src/env.d.ts
vendored
@ -1,7 +1,6 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
import type { ToastUtilities } from '@cherrystudio/ui'
|
||||
import type KeyvStorage from '@kangfenmao/keyv-storage'
|
||||
import type { HookAPI } from 'antd/es/modal/useModal'
|
||||
import type { NavigateFunction } from 'react-router-dom'
|
||||
|
||||
@ -17,7 +16,6 @@ declare global {
|
||||
interface Window {
|
||||
root: HTMLElement
|
||||
modal: HookAPI
|
||||
keyv: KeyvStorage
|
||||
store: any
|
||||
navigate: NavigateFunction
|
||||
toast: ToastUtilities
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import { throttle } from 'lodash'
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
@ -9,12 +10,12 @@ export default function useScrollPosition(key: string) {
|
||||
const handleScroll = throttle(() => {
|
||||
const position = containerRef.current?.scrollTop ?? 0
|
||||
window.requestAnimationFrame(() => {
|
||||
window.keyv.set(scrollKey, position)
|
||||
cacheService.set(scrollKey, position)
|
||||
})
|
||||
}, 100)
|
||||
|
||||
useEffect(() => {
|
||||
const scroll = () => containerRef.current?.scrollTo({ top: window.keyv.get(scrollKey) || 0 })
|
||||
const scroll = () => containerRef.current?.scrollTo({ top: cacheService.get(scrollKey) || 0 })
|
||||
scroll()
|
||||
clearTimeout(scrollTimerRef.current)
|
||||
scrollTimerRef.current = setTimeout(scroll, 50)
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { preferenceService } from '@data/PreferenceService'
|
||||
import KeyvStorage from '@kangfenmao/keyv-storage'
|
||||
import { loggerService } from '@logger'
|
||||
|
||||
import { startAutoSync } from './services/BackupService'
|
||||
@ -8,11 +7,6 @@ import storeSyncService from './services/StoreSyncService'
|
||||
import { webTraceService } from './services/WebTraceService'
|
||||
loggerService.initWindowSource('mainWindow')
|
||||
|
||||
function initKeyv() {
|
||||
window.keyv = new KeyvStorage()
|
||||
window.keyv.init()
|
||||
}
|
||||
|
||||
function initAutoSync() {
|
||||
setTimeout(async () => {
|
||||
const autoSyncStates = await preferenceService.getMultiple({
|
||||
@ -39,7 +33,6 @@ function initWebTrace() {
|
||||
webTraceService.init()
|
||||
}
|
||||
|
||||
initKeyv()
|
||||
initAutoSync()
|
||||
initStoreSync()
|
||||
initWebTrace()
|
||||
|
||||
@ -137,7 +137,7 @@ const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic,
|
||||
|
||||
const onClearMessages = useCallback(
|
||||
(topic: Topic) => {
|
||||
// window.keyv.set(EVENT_NAMES.CHAT_COMPLETION_PAUSED, true)
|
||||
// cacheService.set(EVENT_NAMES.CHAT_COMPLETION_PAUSED, true)
|
||||
setGenerating(false)
|
||||
EventEmitter.emit(EVENT_NAMES.CLEAR_MESSAGES, topic)
|
||||
},
|
||||
|
||||
@ -2,6 +2,7 @@ import { ExclamationCircleOutlined } from '@ant-design/icons'
|
||||
import { RowFlex } from '@cherrystudio/ui'
|
||||
import { Flex } from '@cherrystudio/ui'
|
||||
import { Switch } from '@cherrystudio/ui'
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import { loggerService } from '@logger'
|
||||
import { DeleteIcon, EditIcon, LoadingIcon, RefreshIcon } from '@renderer/components/Icons'
|
||||
import TextBadge from '@renderer/components/TextBadge'
|
||||
@ -479,8 +480,8 @@ const MemorySettings = () => {
|
||||
const handleSettingsSubmit = async () => {
|
||||
setSettingsModalVisible(false)
|
||||
await memoryService.updateConfig()
|
||||
if (window.keyv.get('memory.wait.settings')) {
|
||||
window.keyv.remove('memory.wait.settings')
|
||||
if (cacheService.get('memory.wait.settings')) {
|
||||
cacheService.delete('memory.wait.settings')
|
||||
dispatch(setGlobalMemoryEnabled(true))
|
||||
}
|
||||
}
|
||||
@ -488,7 +489,7 @@ const MemorySettings = () => {
|
||||
const handleSettingsCancel = () => {
|
||||
setSettingsModalVisible(false)
|
||||
form.resetFields()
|
||||
window.keyv.remove('memory.wait.settings')
|
||||
cacheService.delete('memory.wait.settings')
|
||||
}
|
||||
|
||||
const handleResetMemories = async (userId: string) => {
|
||||
@ -554,7 +555,7 @@ const MemorySettings = () => {
|
||||
|
||||
const handleGlobalMemoryToggle = async (enabled: boolean) => {
|
||||
if (enabled && !embedderModel) {
|
||||
window.keyv.set('memory.wait.settings', true)
|
||||
cacheService.set('memory.wait.settings', true)
|
||||
return setSettingsModalVisible(true)
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import type { WebSearchState } from '@renderer/store/websearch'
|
||||
import type { WebSearchProvider, WebSearchProviderResponse } from '@renderer/types'
|
||||
|
||||
@ -38,16 +39,16 @@ export default abstract class BaseWebSearchProvider {
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const lastUsedKey = window.keyv.get(keyName)
|
||||
if (!lastUsedKey) {
|
||||
window.keyv.set(keyName, keys[0])
|
||||
const lastUsedKey = cacheService.getShared(keyName) as string | undefined
|
||||
if (lastUsedKey === undefined) {
|
||||
cacheService.setShared(keyName, keys[0])
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const currentIndex = keys.indexOf(lastUsedKey)
|
||||
const nextIndex = (currentIndex + 1) % keys.length
|
||||
const nextKey = keys[nextIndex]
|
||||
window.keyv.set(keyName, nextKey)
|
||||
cacheService.setShared(keyName, nextKey)
|
||||
|
||||
return nextKey
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import { loggerService } from '@logger'
|
||||
import { getModel } from '@renderer/hooks/useModel'
|
||||
import type { AssistantMessage } from '@renderer/types'
|
||||
@ -103,7 +104,7 @@ export class MemoryProcessor {
|
||||
if (!memoryConfig.llmApiClient) {
|
||||
throw new Error('No LLM model configured for memory processing')
|
||||
}
|
||||
const existingMemoriesResult = (window.keyv.get(`memory-search-${lastMessageId}`) as MemoryItem[]) || []
|
||||
const existingMemoriesResult = (cacheService.get(`memory-search-${lastMessageId}`) as MemoryItem[]) || []
|
||||
|
||||
const existingMemories = existingMemoriesResult.map((memory) => ({
|
||||
id: memory.id,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import type { OcrApiProvider, OcrHandler } from '@renderer/types'
|
||||
|
||||
export abstract class OcrBaseApiClient {
|
||||
public provider: OcrApiProvider
|
||||
protected host: string
|
||||
@ -27,16 +27,16 @@ export abstract class OcrBaseApiClient {
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const lastUsedKey = window.keyv.get(keyName)
|
||||
if (!lastUsedKey) {
|
||||
window.keyv.set(keyName, keys[0])
|
||||
const lastUsedKey = cacheService.getShared(keyName) as string | undefined
|
||||
if (lastUsedKey === undefined) {
|
||||
cacheService.setShared(keyName, keys[0])
|
||||
return keys[0]
|
||||
}
|
||||
|
||||
const currentIndex = keys.indexOf(lastUsedKey)
|
||||
const nextIndex = (currentIndex + 1) % keys.length
|
||||
const nextKey = keys[nextIndex]
|
||||
window.keyv.set(keyName, nextKey)
|
||||
cacheService.setShared(keyName, nextKey)
|
||||
|
||||
return nextKey
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { cacheService } from '@data/CacheService'
|
||||
import { loggerService } from '@logger'
|
||||
import db from '@renderer/databases'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
@ -610,8 +611,8 @@ export const resendMessageThunk =
|
||||
// Clear cached search results for the user message being resent
|
||||
// This ensures that the regenerated responses will not use stale search results
|
||||
try {
|
||||
window.keyv.remove(`web-search-${userMessageToResend.id}`)
|
||||
window.keyv.remove(`knowledge-search-${userMessageToResend.id}`)
|
||||
cacheService.delete(`web-search-${userMessageToResend.id}`)
|
||||
cacheService.delete(`knowledge-search-${userMessageToResend.id}`)
|
||||
} catch (error) {
|
||||
logger.warn(`Failed to clear keyv cache for message ${userMessageToResend.id}:`, error as Error)
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import '@renderer/assets/styles/index.css'
|
||||
import '@renderer/assets/styles/tailwind.css'
|
||||
import '@ant-design/v5-patch-for-react-19'
|
||||
|
||||
import KeyvStorage from '@kangfenmao/keyv-storage'
|
||||
import { loggerService } from '@logger'
|
||||
import storeSyncService from '@renderer/services/StoreSyncService'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
@ -11,18 +10,6 @@ import MiniWindowApp from './MiniWindowApp'
|
||||
|
||||
loggerService.initWindowSource('MiniWindow')
|
||||
|
||||
/**
|
||||
* This function is required for model API
|
||||
* eg. BaseProviders.ts
|
||||
* Although the coupling is too strong, we have no choice but to load it
|
||||
* In multi-window handling, decoupling is needed
|
||||
*/
|
||||
function initKeyv() {
|
||||
window.keyv = new KeyvStorage()
|
||||
window.keyv.init()
|
||||
}
|
||||
initKeyv()
|
||||
|
||||
//subscribe to store sync
|
||||
storeSyncService.subscribe()
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ import '@ant-design/v5-patch-for-react-19'
|
||||
|
||||
import { getToastUtilities } from '@cherrystudio/ui'
|
||||
import { preferenceService } from '@data/PreferenceService'
|
||||
import KeyvStorage from '@kangfenmao/keyv-storage'
|
||||
import { loggerService } from '@logger'
|
||||
import { ToastPortal } from '@renderer/components/ToastPortal'
|
||||
import AntdProvider from '@renderer/context/AntdProvider'
|
||||
@ -33,17 +32,6 @@ await preferenceService.preload([
|
||||
'feature.selection.action_window_opacity'
|
||||
])
|
||||
|
||||
/**
|
||||
* fetchChatCompletion depends on this,
|
||||
* which is not a good design, but we have to add it for now
|
||||
*/
|
||||
function initKeyv() {
|
||||
window.keyv = new KeyvStorage()
|
||||
window.keyv.init()
|
||||
}
|
||||
|
||||
initKeyv()
|
||||
|
||||
//subscribe to store sync
|
||||
storeSyncService.subscribe()
|
||||
|
||||
|
||||
@ -7188,13 +7188,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@kangfenmao/keyv-storage@npm:^0.1.0":
|
||||
version: 0.1.0
|
||||
resolution: "@kangfenmao/keyv-storage@npm:0.1.0"
|
||||
checksum: 10c0/647cf2d2f2e403ec91d1835546aa08bc6af1468a2823c3aa2cef883bacf67eb1a88bb97be1b4c0a09bc3ed69dba2ccbb8ecc3fd13242e84d4e234d5b77707156
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@langchain/community@npm:^0.3.50":
|
||||
version: 0.3.54
|
||||
resolution: "@langchain/community@npm:0.3.54"
|
||||
@ -14952,7 +14945,6 @@ __metadata:
|
||||
"@google/genai": "patch:@google/genai@npm%3A1.0.1#~/.yarn/patches/@google-genai-npm-1.0.1-e26f0f9af7.patch"
|
||||
"@hello-pangea/dnd": "npm:^18.0.1"
|
||||
"@heroui/react": "npm:^2.8.3"
|
||||
"@kangfenmao/keyv-storage": "npm:^0.1.0"
|
||||
"@langchain/community": "npm:^0.3.50"
|
||||
"@libsql/client": "npm:0.14.0"
|
||||
"@libsql/win32-x64-msvc": "npm:^0.4.7"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user