From 1139d8d57ad399c08d32400dcc5617a705c6c66c Mon Sep 17 00:00:00 2001 From: fullex <0xfullex@gmail.com> Date: Tue, 9 Dec 2025 13:02:39 +0800 Subject: [PATCH] feat: enhance cache service with casual methods and update related components - Introduced casual methods (`getCasual`, `setCasual`, `deleteCasual`, etc.) in `CacheService` for dynamic key handling. - Updated various components to utilize the new casual methods for improved flexibility in cache management. - Added new cache schema keys for file and resource paths in `cacheSchemas.ts`. - Refactored `UserPopup`, `useAppInit`, and other components to align with the new caching strategy, ensuring consistent access to cached data. --- packages/shared/data/cache/cacheSchemas.ts | 6 +- .../aiCore/legacy/clients/BaseApiClient.ts | 16 +- .../src/components/Popups/UserPopup.tsx | 6 +- src/renderer/src/data/CacheService.ts | 229 ++++++++++++++---- src/renderer/src/data/README.md | 19 +- src/renderer/src/data/hooks/useCache.ts | 8 +- src/renderer/src/hooks/useAppInit.ts | 6 +- src/renderer/src/hooks/useModel.ts | 2 +- src/renderer/src/hooks/useScrollPosition.ts | 4 +- src/renderer/src/hooks/useTopic.ts | 16 +- .../home/Inputbar/AgentSessionInputbar.tsx | 4 +- .../src/pages/home/Inputbar/Inputbar.tsx | 8 +- .../home/Messages/Blocks/CitationBlock.tsx | 2 +- .../pages/paintings/utils/TokenFluxService.ts | 4 +- .../MemorySettings/MemorySettings.tsx | 8 +- .../pages/store/assistants/presets/index.ts | 2 +- .../BaseWebSearchProvider.ts | 6 +- src/renderer/src/services/ApiService.ts | 6 +- src/renderer/src/services/FileManager.ts | 6 +- src/renderer/src/services/MemoryProcessor.ts | 2 +- .../services/ocr/clients/OcrBaseApiClient.ts | 6 +- src/renderer/src/store/thunk/messageThunk.ts | 4 +- 22 files changed, 258 insertions(+), 112 deletions(-) diff --git a/packages/shared/data/cache/cacheSchemas.ts b/packages/shared/data/cache/cacheSchemas.ts index 93cd35c054..4a3dd7f313 100644 --- a/packages/shared/data/cache/cacheSchemas.ts +++ b/packages/shared/data/cache/cacheSchemas.ts @@ -31,6 +31,9 @@ export type UseCacheSchema = { 'app.dist.update_state': CacheValueTypes.CacheAppUpdateState 'app.user.avatar': string + 'app.path.files': string + 'app.path.resources': string + // Chat context 'chat.multi_select_mode': boolean 'chat.selected_message_ids': string[] @@ -62,7 +65,8 @@ export const DefaultUseCache: UseCacheSchema = { ignore: false }, 'app.user.avatar': '', - + 'app.path.files': '', + 'app.path.resources': '', // Chat context 'chat.multi_select_mode': false, 'chat.selected_message_ids': [], diff --git a/src/renderer/src/aiCore/legacy/clients/BaseApiClient.ts b/src/renderer/src/aiCore/legacy/clients/BaseApiClient.ts index d1101c4ca0..57cfa02a32 100644 --- a/src/renderer/src/aiCore/legacy/clients/BaseApiClient.ts +++ b/src/renderer/src/aiCore/legacy/clients/BaseApiClient.ts @@ -175,16 +175,16 @@ export abstract class BaseApiClient< return keys[0] } - const lastUsedKey = cacheService.getShared(keyName) as string | undefined + const lastUsedKey = cacheService.getSharedCasual(keyName) if (lastUsedKey === undefined) { - cacheService.setShared(keyName, keys[0]) + cacheService.setSharedCasual(keyName, keys[0]) return keys[0] } const currentIndex = keys.indexOf(lastUsedKey) const nextIndex = (currentIndex + 1) % keys.length const nextKey = keys[nextIndex] - cacheService.setShared(keyName, nextKey) + cacheService.setSharedCasual(keyName, nextKey) return nextKey } @@ -343,7 +343,7 @@ export abstract class BaseApiClient< } private getMemoryReferencesFromCache(message: Message) { - const memories = cacheService.get(`memory-search-${message.id}`) as MemoryItem[] | undefined + const memories = cacheService.getCasual(`memory-search-${message.id}`) if (memories) { const memoryReferences: KnowledgeReference[] = memories.map((mem, index) => ({ id: index + 1, @@ -361,10 +361,10 @@ export abstract class BaseApiClient< if (isEmpty(content)) { return [] } - const webSearch: WebSearchResponse | undefined = cacheService.get(`web-search-${message.id}`) + const webSearch = cacheService.getCasual(`web-search-${message.id}`) if (webSearch) { - cacheService.delete(`web-search-${message.id}`) + cacheService.deleteCasual(`web-search-${message.id}`) return (webSearch.results as WebSearchProviderResponse).results.map( (result, index) => ({ @@ -387,10 +387,10 @@ export abstract class BaseApiClient< if (isEmpty(content)) { return [] } - const knowledgeReferences: KnowledgeReference[] | undefined = cacheService.get(`knowledge-search-${message.id}`) + const knowledgeReferences = cacheService.getCasual(`knowledge-search-${message.id}`) if (knowledgeReferences && !isEmpty(knowledgeReferences)) { - cacheService.delete(`knowledge-search-${message.id}`) + cacheService.deleteCasual(`knowledge-search-${message.id}`) logger.debug(`Found ${knowledgeReferences.length} knowledge base references in cache for ID: ${message.id}`) return knowledgeReferences } diff --git a/src/renderer/src/components/Popups/UserPopup.tsx b/src/renderer/src/components/Popups/UserPopup.tsx index b627e42135..26a3d5e82e 100644 --- a/src/renderer/src/components/Popups/UserPopup.tsx +++ b/src/renderer/src/components/Popups/UserPopup.tsx @@ -44,7 +44,7 @@ const PopupContainer: React.FC = ({ resolve }) => { // set emoji string await ImageStorage.set('avatar', emoji) // update avatar display - cacheService.set('avatar', emoji) + cacheService.set('app.user.avatar', emoji) setEmojiPickerOpen(false) } catch (error: any) { window.toast.error(error.message) @@ -53,7 +53,7 @@ const PopupContainer: React.FC = ({ resolve }) => { const handleReset = async () => { try { await ImageStorage.set('avatar', DefaultAvatar) - cacheService.set('avatar', DefaultAvatar) + cacheService.set('app.user.avatar', DefaultAvatar) setDropdownOpen(false) } catch (error: any) { window.toast.error(error.message) @@ -78,7 +78,7 @@ const PopupContainer: React.FC = ({ resolve }) => { const compressedFile = await compressImage(_file) await ImageStorage.set('avatar', compressedFile) } - cacheService.set('avatar', await ImageStorage.get('avatar')) + cacheService.set('app.user.avatar', await ImageStorage.get('avatar')) setDropdownOpen(false) } catch (error: any) { window.toast.error(error.message) diff --git a/src/renderer/src/data/CacheService.ts b/src/renderer/src/data/CacheService.ts index 9a1602adcf..7fe9a2d7a7 100644 --- a/src/renderer/src/data/CacheService.ts +++ b/src/renderer/src/data/CacheService.ts @@ -93,13 +93,27 @@ export class CacheService { // ============ Memory Cache (Cross-component) ============ /** - * Get value from memory cache with TTL validation - * @param key - Cache key to retrieve + * Get value from memory cache with TTL validation (type-safe) + * @param key - Schema-defined cache key * @returns Cached value or undefined if not found or expired */ - get(key: K): UseCacheSchema[K] - get(key: Exclude): T | undefined - get(key: string): any { + get(key: K): UseCacheSchema[K] { + return this.getInternal(key) + } + + /** + * Get value from memory cache with TTL validation (casual, dynamic key) + * @param key - Dynamic cache key (e.g., `topic:${id}`) + * @returns Cached value or undefined if not found or expired + */ + getCasual(key: Exclude): T | undefined { + return this.getInternal(key) + } + + /** + * Internal implementation for memory cache get + */ + private getInternal(key: string): any { const entry = this.memoryCache.get(key) if (entry === undefined) { return undefined @@ -115,14 +129,29 @@ export class CacheService { } /** - * Set value in memory cache with optional TTL - * @param key - Cache key to store + * Set value in memory cache with optional TTL (type-safe) + * @param key - Schema-defined cache key + * @param value - Value to cache (type inferred from schema) + * @param ttl - Time to live in milliseconds (optional) + */ + set(key: K, value: UseCacheSchema[K], ttl?: number): void { + this.setInternal(key, value, ttl) + } + + /** + * Set value in memory cache with optional TTL (casual, dynamic key) + * @param key - Dynamic cache key (e.g., `topic:${id}`) * @param value - Value to cache * @param ttl - Time to live in milliseconds (optional) */ - set(key: K, value: UseCacheSchema[K]): void - set(key: Exclude, value: T, ttl?: number): void - set(key: string, value: any, ttl?: number): void { + setCasual(key: Exclude, value: T, ttl?: number): void { + this.setInternal(key, value, ttl) + } + + /** + * Internal implementation for memory cache set + */ + private setInternal(key: string, value: any, ttl?: number): void { const existingEntry = this.memoryCache.get(key) // Value comparison optimization @@ -149,14 +178,27 @@ export class CacheService { } /** - * Check if key exists in memory cache and is not expired - * @param key - Cache key to check + * Check if key exists in memory cache and is not expired (type-safe) + * @param key - Schema-defined cache key * @returns True if key exists and is valid, false otherwise */ + has(key: K): boolean { + return this.hasInternal(key) + } - has(key: K): boolean - has(key: Exclude): boolean - has(key: string): boolean { + /** + * Check if key exists in memory cache and is not expired (casual, dynamic key) + * @param key - Dynamic cache key + * @returns True if key exists and is valid, false otherwise + */ + hasCasual(key: Exclude): boolean { + return this.hasInternal(key) + } + + /** + * Internal implementation for memory cache has + */ + private hasInternal(key: string): boolean { const entry = this.memoryCache.get(key) if (entry === undefined) { return false @@ -173,13 +215,27 @@ export class CacheService { } /** - * Delete from memory cache with hook protection - * @param key - Cache key to delete + * Delete from memory cache with hook protection (type-safe) + * @param key - Schema-defined cache key * @returns True if deletion succeeded, false if key is protected by active hooks */ - delete(key: K): boolean - delete(key: Exclude): boolean - delete(key: string): boolean { + delete(key: K): boolean { + return this.deleteInternal(key) + } + + /** + * Delete from memory cache with hook protection (casual, dynamic key) + * @param key - Dynamic cache key + * @returns True if deletion succeeded, false if key is protected by active hooks + */ + deleteCasual(key: Exclude): boolean { + return this.deleteInternal(key) + } + + /** + * Internal implementation for memory cache delete + */ + private deleteInternal(key: string): boolean { // Check if key is being used by hooks if (this.activeHooks.has(key)) { logger.error(`Cannot delete key "${key}" as it's being used by useCache hook`) @@ -199,25 +255,41 @@ export class CacheService { } /** - * Check if a key has TTL set in memory cache - * @param key - Cache key to check + * Check if a key has TTL set in memory cache (type-safe) + * @param key - Schema-defined cache key * @returns True if key has TTL configured */ - hasTTL(key: K): boolean - hasTTL(key: Exclude): boolean - hasTTL(key: string): boolean { + hasTTL(key: K): boolean { const entry = this.memoryCache.get(key) return entry?.expireAt !== undefined } /** - * Check if a shared cache key has TTL set - * @param key - Shared cache key to check + * Check if a key has TTL set in memory cache (casual, dynamic key) + * @param key - Dynamic cache key * @returns True if key has TTL configured */ - hasSharedTTL(key: K): boolean - hasSharedTTL(key: Exclude): boolean - hasSharedTTL(key: string): boolean { + hasTTLCasual(key: Exclude): boolean { + const entry = this.memoryCache.get(key) + return entry?.expireAt !== undefined + } + + /** + * Check if a shared cache key has TTL set (type-safe) + * @param key - Schema-defined shared cache key + * @returns True if key has TTL configured + */ + hasSharedTTL(key: K): boolean { + const entry = this.sharedCache.get(key) + return entry?.expireAt !== undefined + } + + /** + * Check if a shared cache key has TTL set (casual, dynamic key) + * @param key - Dynamic shared cache key + * @returns True if key has TTL configured + */ + hasSharedTTLCasual(key: Exclude): boolean { const entry = this.sharedCache.get(key) return entry?.expireAt !== undefined } @@ -225,13 +297,27 @@ export class CacheService { // ============ Shared Cache (Cross-window) ============ /** - * Get value from shared cache with TTL validation - * @param key - Shared cache key to retrieve + * Get value from shared cache with TTL validation (type-safe) + * @param key - Schema-defined shared cache key * @returns Cached value or undefined if not found or expired */ - getShared(key: K): UseSharedCacheSchema[K] - getShared(key: Exclude): T | undefined - getShared(key: string): any { + getShared(key: K): UseSharedCacheSchema[K] | undefined { + return this.getSharedInternal(key) + } + + /** + * Get value from shared cache with TTL validation (casual, dynamic key) + * @param key - Dynamic shared cache key (e.g., `window:${id}`) + * @returns Cached value or undefined if not found or expired + */ + getSharedCasual(key: Exclude): T | undefined { + return this.getSharedInternal(key) + } + + /** + * Internal implementation for shared cache get + */ + private getSharedInternal(key: string): any { const entry = this.sharedCache.get(key) if (!entry) return undefined @@ -246,14 +332,29 @@ export class CacheService { } /** - * Set value in shared cache with cross-window synchronization - * @param key - Shared cache key to store + * Set value in shared cache with cross-window synchronization (type-safe) + * @param key - Schema-defined shared cache key + * @param value - Value to cache (type inferred from schema) + * @param ttl - Time to live in milliseconds (optional) + */ + setShared(key: K, value: UseSharedCacheSchema[K], ttl?: number): void { + this.setSharedInternal(key, value, ttl) + } + + /** + * Set value in shared cache with cross-window synchronization (casual, dynamic key) + * @param key - Dynamic shared cache key (e.g., `window:${id}`) * @param value - Value to cache * @param ttl - Time to live in milliseconds (optional) */ - setShared(key: K, value: UseSharedCacheSchema[K]): void - setShared(key: Exclude, value: T, ttl?: number): void - setShared(key: string, value: any, ttl?: number): void { + setSharedCasual(key: Exclude, value: T, ttl?: number): void { + this.setSharedInternal(key, value, ttl) + } + + /** + * Internal implementation for shared cache set + */ + private setSharedInternal(key: string, value: any, ttl?: number): void { const existingEntry = this.sharedCache.get(key) // Value comparison optimization @@ -296,13 +397,27 @@ export class CacheService { } /** - * Check if key exists in shared cache and is not expired - * @param key - Shared cache key to check + * Check if key exists in shared cache and is not expired (type-safe) + * @param key - Schema-defined shared cache key * @returns True if key exists and is valid, false otherwise */ - hasShared(key: K): boolean - hasShared(key: Exclude): boolean - hasShared(key: string): boolean { + hasShared(key: K): boolean { + return this.hasSharedInternal(key) + } + + /** + * Check if key exists in shared cache and is not expired (casual, dynamic key) + * @param key - Dynamic shared cache key + * @returns True if key exists and is valid, false otherwise + */ + hasSharedCasual(key: Exclude): boolean { + return this.hasSharedInternal(key) + } + + /** + * Internal implementation for shared cache has + */ + private hasSharedInternal(key: string): boolean { const entry = this.sharedCache.get(key) if (!entry) return false @@ -317,13 +432,27 @@ export class CacheService { } /** - * Delete from shared cache with cross-window synchronization and hook protection - * @param key - Shared cache key to delete + * Delete from shared cache with cross-window synchronization and hook protection (type-safe) + * @param key - Schema-defined shared cache key * @returns True if deletion succeeded, false if key is protected by active hooks */ - deleteShared(key: K): boolean - deleteShared(key: Exclude): boolean - deleteShared(key: string): boolean { + deleteShared(key: K): boolean { + return this.deleteSharedInternal(key) + } + + /** + * Delete from shared cache with cross-window synchronization and hook protection (casual, dynamic key) + * @param key - Dynamic shared cache key + * @returns True if deletion succeeded, false if key is protected by active hooks + */ + deleteSharedCasual(key: Exclude): boolean { + return this.deleteSharedInternal(key) + } + + /** + * Internal implementation for shared cache delete + */ + private deleteSharedInternal(key: string): boolean { // Check if key is being used by hooks if (this.activeHooks.has(key)) { logger.error(`Cannot delete key "${key}" as it's being used by useSharedCache hook`) diff --git a/src/renderer/src/data/README.md b/src/renderer/src/data/README.md index 1267685e8d..850d887488 100644 --- a/src/renderer/src/data/README.md +++ b/src/renderer/src/data/README.md @@ -156,19 +156,32 @@ await preferenceService.setMultiple({ ```typescript import { cacheService } from '@data/CacheService' -// Memory cache (component-level) +// Memory cache - Type-safe (schema key, with auto-completion) cacheService.set('temp.calculation', result, 30000) // 30s TTL const result = cacheService.get('temp.calculation') -// Shared cache (cross-window) +// Memory cache - Casual (dynamic key, requires manual type) +cacheService.setCasual(`topic:${id}`, topicData) +const topic = cacheService.getCasual(`topic:${id}`) + +// Shared cache - Type-safe (schema key) cacheService.setShared('window.layout', layoutConfig) const layout = cacheService.getShared('window.layout') -// Persist cache (survives restarts) +// Shared cache - Casual (dynamic key) +cacheService.setSharedCasual(`window:${windowId}`, state) +const state = cacheService.getSharedCasual(`window:${windowId}`) + +// Persist cache (survives restarts, schema keys only) cacheService.setPersist('app.recent_files', recentFiles) const files = cacheService.getPersist('app.recent_files') ``` +**When to Use Type-safe vs Casual Methods**: +- **Type-safe** (`get`, `set`, `getShared`, `setShared`): Use when the key is predefined in the cache schema. Provides auto-completion and type inference. +- **Casual** (`getCasual`, `setCasual`, `getSharedCasual`, `setSharedCasual`): Use when the key is dynamically constructed (e.g., `topic:${id}`). Requires manual type specification via generics. +- **Persist Cache**: Only supports schema keys (no Casual methods) to ensure data integrity. + ## React Hooks ### useDataApi diff --git a/src/renderer/src/data/hooks/useCache.ts b/src/renderer/src/data/hooks/useCache.ts index 61e7328188..7689b62f32 100644 --- a/src/renderer/src/data/hooks/useCache.ts +++ b/src/renderer/src/data/hooks/useCache.ts @@ -44,8 +44,8 @@ export function useCache( */ const value = useSyncExternalStore( useCallback((callback) => cacheService.subscribe(key, callback), [key]), - useCallback(() => cacheService.get(key), [key]), - useCallback(() => cacheService.get(key), [key]) // SSR snapshot + useCallback(() => cacheService.get(key), [key]), + useCallback(() => cacheService.get(key), [key]) // SSR snapshot ) /** @@ -131,8 +131,8 @@ export function useSharedCache( */ const value = useSyncExternalStore( useCallback((callback) => cacheService.subscribe(key, callback), [key]), - useCallback(() => cacheService.getShared(key), [key]), - useCallback(() => cacheService.getShared(key), [key]) // SSR snapshot + useCallback(() => cacheService.getShared(key), [key]), + useCallback(() => cacheService.getShared(key), [key]) // SSR snapshot ) /** diff --git a/src/renderer/src/hooks/useAppInit.ts b/src/renderer/src/hooks/useAppInit.ts index 9c747033a9..b1ccf7da23 100644 --- a/src/renderer/src/hooks/useAppInit.ts +++ b/src/renderer/src/hooks/useAppInit.ts @@ -79,7 +79,7 @@ export function useAppInit() { useFullScreenNotice() useEffect(() => { - savedAvatar?.value && cacheService.set('avatar', savedAvatar.value) + savedAvatar?.value && cacheService.set('app.user.avatar', savedAvatar.value) }, [savedAvatar]) useEffect(() => { @@ -149,8 +149,8 @@ export function useAppInit() { useEffect(() => { // set files path window.api.getAppInfo().then((info) => { - cacheService.set('filesPath', info.filesPath) - cacheService.set('resourcesPath', info.resourcesPath) + cacheService.set('app.path.files', info.filesPath) + cacheService.set('app.path.resources', info.resourcesPath) }) }, []) diff --git a/src/renderer/src/hooks/useModel.ts b/src/renderer/src/hooks/useModel.ts index 1bd298fa48..763347cc36 100644 --- a/src/renderer/src/hooks/useModel.ts +++ b/src/renderer/src/hooks/useModel.ts @@ -29,7 +29,7 @@ export function getModel(id?: string, providerId?: string) { } export function modelGenerating() { - const generating = cacheService.get('generating') ?? false + const generating = cacheService.get('chat.generating') ?? false if (generating) { window.toast.warning(i18n.t('message.switch.disabled')) diff --git a/src/renderer/src/hooks/useScrollPosition.ts b/src/renderer/src/hooks/useScrollPosition.ts index dc6f70b9c5..f7c0393aad 100644 --- a/src/renderer/src/hooks/useScrollPosition.ts +++ b/src/renderer/src/hooks/useScrollPosition.ts @@ -24,12 +24,12 @@ export default function useScrollPosition(key: string, throttleWait?: number) { const handleScroll = throttle(() => { const position = containerRef.current?.scrollTop ?? 0 window.requestAnimationFrame(() => { - cacheService.set(scrollKeyRef.current, position) + cacheService.setCasual(scrollKeyRef.current, position) }) }, throttleWait ?? 100) useEffect(() => { - const scroll = () => containerRef.current?.scrollTo({ top: cacheService.get(scrollKey) || 0 }) + const scroll = () => containerRef.current?.scrollTo({ top: cacheService.getCasual(scrollKey) || 0 }) scroll() setTimeoutTimer('scrollEffect', scroll, 50) }, [scrollKey, setTimeoutTimer]) diff --git a/src/renderer/src/hooks/useTopic.ts b/src/renderer/src/hooks/useTopic.ts index a85fde5038..d8f7a017ea 100644 --- a/src/renderer/src/hooks/useTopic.ts +++ b/src/renderer/src/hooks/useTopic.ts @@ -82,9 +82,9 @@ export async function getTopicById(topicId: string) { * 开始重命名指定话题 */ export const startTopicRenaming = (topicId: string) => { - const currentIds = cacheService.get('renamingTopics') ?? [] + const currentIds = cacheService.get('topic.renaming') ?? [] if (!currentIds.includes(topicId)) { - cacheService.set('renamingTopics', [...currentIds, topicId]) + cacheService.set('topic.renaming', [...currentIds, topicId]) } } @@ -93,23 +93,23 @@ export const startTopicRenaming = (topicId: string) => { */ export const finishTopicRenaming = (topicId: string) => { // 1. 立即从 renamingTopics 移除 - const renamingTopics = cacheService.get('renamingTopics') + const renamingTopics = cacheService.get('topic.renaming') if (renamingTopics && renamingTopics.includes(topicId)) { cacheService.set( - 'renamingTopics', + 'topic.renaming', renamingTopics.filter((id) => id !== topicId) ) } // 2. 立即添加到 newlyRenamedTopics - const currentNewlyRenamed = cacheService.get('newlyRenamedTopics') ?? [] - cacheService.set('newlyRenamedTopics', [...currentNewlyRenamed, topicId]) + const currentNewlyRenamed = cacheService.get('topic.newly_renamed') ?? [] + cacheService.set('topic.newly_renamed', [...currentNewlyRenamed, topicId]) // 3. 延迟从 newlyRenamedTopics 移除 setTimeout(() => { - const current = cacheService.get('newlyRenamedTopics') ?? [] + const current = cacheService.get('topic.newly_renamed') ?? [] cacheService.set( - 'newlyRenamedTopics', + 'topic.newly_renamed', current.filter((id) => id !== topicId) ) }, 700) diff --git a/src/renderer/src/pages/home/Inputbar/AgentSessionInputbar.tsx b/src/renderer/src/pages/home/Inputbar/AgentSessionInputbar.tsx index 80915f93d1..afc7e01ca9 100644 --- a/src/renderer/src/pages/home/Inputbar/AgentSessionInputbar.tsx +++ b/src/renderer/src/pages/home/Inputbar/AgentSessionInputbar.tsx @@ -169,8 +169,8 @@ const AgentSessionInputbarInner: FC = ({ assistant, agentId, session setText, isEmpty: inputEmpty } = useInputText({ - initialValue: cacheService.get(draftCacheKey) ?? '', - onChange: (value) => cacheService.set(draftCacheKey, value, DRAFT_CACHE_TTL) + initialValue: cacheService.getCasual(draftCacheKey) ?? '', + onChange: (value) => cacheService.setCasual(draftCacheKey, value, DRAFT_CACHE_TTL) }) const { textareaRef, diff --git a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx index a514bd3bd2..e223a64e96 100644 --- a/src/renderer/src/pages/home/Inputbar/Inputbar.tsx +++ b/src/renderer/src/pages/home/Inputbar/Inputbar.tsx @@ -57,7 +57,7 @@ const DRAFT_CACHE_TTL = 24 * 60 * 60 * 1000 // 24 hours const getMentionedModelsCacheKey = (assistantId: string) => `inputbar-mentioned-models-${assistantId}` const getValidatedCachedModels = (assistantId: string): Model[] => { - const cached = cacheService.get(getMentionedModelsCacheKey(assistantId)) + const cached = cacheService.getCasual(getMentionedModelsCacheKey(assistantId)) if (!Array.isArray(cached)) return [] return cached.filter((model) => model?.id && model?.name) } @@ -135,8 +135,8 @@ const InputbarInner: FC = ({ assistant: initialAssistant, se const { setCouldAddImageFile } = useInputbarToolsInternalDispatch() const { text, setText } = useInputText({ - initialValue: cacheService.get(INPUTBAR_DRAFT_CACHE_KEY) ?? '', - onChange: (value) => cacheService.set(INPUTBAR_DRAFT_CACHE_KEY, value, DRAFT_CACHE_TTL) + initialValue: cacheService.getCasual(INPUTBAR_DRAFT_CACHE_KEY) ?? '', + onChange: (value) => cacheService.setCasual(INPUTBAR_DRAFT_CACHE_KEY, value, DRAFT_CACHE_TTL) }) const { textareaRef, @@ -210,7 +210,7 @@ const InputbarInner: FC = ({ assistant: initialAssistant, se }, [canAddImageFile, setCouldAddImageFile]) const onUnmount = useEffectEvent((id: string) => { - cacheService.set(getMentionedModelsCacheKey(id), mentionedModels, DRAFT_CACHE_TTL) + cacheService.setCasual(getMentionedModelsCacheKey(id), mentionedModels, DRAFT_CACHE_TTL) }) useEffect(() => { diff --git a/src/renderer/src/pages/home/Messages/Blocks/CitationBlock.tsx b/src/renderer/src/pages/home/Messages/Blocks/CitationBlock.tsx index 06ac3b36c9..148fd05147 100644 --- a/src/renderer/src/pages/home/Messages/Blocks/CitationBlock.tsx +++ b/src/renderer/src/pages/home/Messages/Blocks/CitationBlock.tsx @@ -30,7 +30,7 @@ function CitationBlock({ block }: { block: CitationMessageBlock }) { }, [formattedCitations, block.knowledge, block.memories, hasGeminiBlock]) const getWebSearchStatusText = (requestId: string) => { - const status = cacheService.get('activeSearches')?.[requestId] ?? { phase: 'default' } + const status = cacheService.getCasual('activeSearches')?.[requestId] ?? { phase: 'default' } switch (status.phase) { case 'fetch_complete': diff --git a/src/renderer/src/pages/paintings/utils/TokenFluxService.ts b/src/renderer/src/pages/paintings/utils/TokenFluxService.ts index d36a69659c..0d70f87c3c 100644 --- a/src/renderer/src/pages/paintings/utils/TokenFluxService.ts +++ b/src/renderer/src/pages/paintings/utils/TokenFluxService.ts @@ -61,7 +61,7 @@ export class TokenFluxService { const cacheKey = `tokenflux_models_${this.apiHost}` // Check cache first - const cachedModels = cacheService.get(cacheKey) + const cachedModels = cacheService.getCasual(cacheKey) if (cachedModels) { return cachedModels } @@ -79,7 +79,7 @@ export class TokenFluxService { } // Cache for 60 minutes (3,600,000 milliseconds) - cacheService.set(cacheKey, data.data, 60 * 60 * 1000) + cacheService.setCasual(cacheKey, data.data, 60 * 60 * 1000) return data.data } diff --git a/src/renderer/src/pages/settings/MemorySettings/MemorySettings.tsx b/src/renderer/src/pages/settings/MemorySettings/MemorySettings.tsx index f42741e6bf..9887589220 100644 --- a/src/renderer/src/pages/settings/MemorySettings/MemorySettings.tsx +++ b/src/renderer/src/pages/settings/MemorySettings/MemorySettings.tsx @@ -475,8 +475,8 @@ const MemorySettings = () => { const handleSettingsSubmit = async () => { setSettingsModalVisible(false) await memoryService.updateConfig() - if (cacheService.get('memory.wait.settings')) { - cacheService.delete('memory.wait.settings') + if (cacheService.getCasual('memory.wait.settings')) { + cacheService.deleteCasual('memory.wait.settings') setGlobalMemoryEnabled(true) } } @@ -484,7 +484,7 @@ const MemorySettings = () => { const handleSettingsCancel = () => { setSettingsModalVisible(false) form.resetFields() - cacheService.delete('memory.wait.settings') + cacheService.deleteCasual('memory.wait.settings') } const handleResetMemories = async (userId: string) => { @@ -550,7 +550,7 @@ const MemorySettings = () => { const handleGlobalMemoryToggle = async (enabled: boolean) => { if (enabled && !embedderModel) { - cacheService.set('memory.wait.settings', true) + cacheService.setCasual('memory.wait.settings', true) return setSettingsModalVisible(true) } diff --git a/src/renderer/src/pages/store/assistants/presets/index.ts b/src/renderer/src/pages/store/assistants/presets/index.ts index 7cc17e2624..b884210442 100644 --- a/src/renderer/src/pages/store/assistants/presets/index.ts +++ b/src/renderer/src/pages/store/assistants/presets/index.ts @@ -28,7 +28,7 @@ export const getAgentsFromSystemAgents = (systemAgents: any) => { export function useSystemAssistantPresets() { const { defaultAgent: defaultPreset } = useSettings() const [presets, setPresets] = useState([]) - const resourcesPath = cacheService.get('resourcesPath') ?? '' + const resourcesPath = cacheService.get('app.path.resources') ?? '' const { agentssubscribeUrl } = store.getState().settings const { i18n } = useTranslation() const currentLanguage = i18n.language diff --git a/src/renderer/src/providers/WebSearchProvider/BaseWebSearchProvider.ts b/src/renderer/src/providers/WebSearchProvider/BaseWebSearchProvider.ts index 0a02c71021..5115be27b7 100644 --- a/src/renderer/src/providers/WebSearchProvider/BaseWebSearchProvider.ts +++ b/src/renderer/src/providers/WebSearchProvider/BaseWebSearchProvider.ts @@ -39,16 +39,16 @@ export default abstract class BaseWebSearchProvider { return keys[0] } - const lastUsedKey = cacheService.getShared(keyName) as string | undefined + const lastUsedKey = cacheService.getSharedCasual(keyName) if (lastUsedKey === undefined) { - cacheService.setShared(keyName, keys[0]) + cacheService.setSharedCasual(keyName, keys[0]) return keys[0] } const currentIndex = keys.indexOf(lastUsedKey) const nextIndex = (currentIndex + 1) % keys.length const nextKey = keys[nextIndex] - cacheService.setShared(keyName, nextKey) + cacheService.setSharedCasual(keyName, nextKey) return nextKey } diff --git a/src/renderer/src/services/ApiService.ts b/src/renderer/src/services/ApiService.ts index 14b84ae383..0c718cbc44 100644 --- a/src/renderer/src/services/ApiService.ts +++ b/src/renderer/src/services/ApiService.ts @@ -468,9 +468,9 @@ function getRotatedApiKey(provider: Provider): string { return keys[0] } - const lastUsedKey = cacheService.get(keyName) as string + const lastUsedKey = cacheService.getCasual(keyName) if (!lastUsedKey) { - cacheService.set(keyName, keys[0]) + cacheService.setCasual(keyName, keys[0]) return keys[0] } @@ -486,7 +486,7 @@ function getRotatedApiKey(provider: Provider): string { const nextIndex = (currentIndex + 1) % keys.length const nextKey = keys[nextIndex] - cacheService.set(keyName, nextKey) + cacheService.setCasual(keyName, nextKey) return nextKey } diff --git a/src/renderer/src/services/FileManager.ts b/src/renderer/src/services/FileManager.ts index e8b0bade7f..cc28ab77bd 100644 --- a/src/renderer/src/services/FileManager.ts +++ b/src/renderer/src/services/FileManager.ts @@ -81,7 +81,7 @@ class FileManager { const file = await db.files.get(id) if (file) { - const filesPath = cacheService.get('filesPath') ?? '' + const filesPath = cacheService.get('app.path.files') ?? '' file.path = filesPath + '/' + file.id + file.ext } @@ -89,7 +89,7 @@ class FileManager { } static getFilePath(file: FileMetadata) { - const filesPath = cacheService.get('filesPath') ?? '' + const filesPath = cacheService.get('app.path.files') ?? '' return filesPath + '/' + file.id + file.ext } @@ -137,7 +137,7 @@ class FileManager { } static getFileUrl(file: FileMetadata) { - const filesPath = cacheService.get('filesPath') ?? '' + const filesPath = cacheService.get('app.path.files') ?? '' return 'file://' + filesPath + '/' + file.name } diff --git a/src/renderer/src/services/MemoryProcessor.ts b/src/renderer/src/services/MemoryProcessor.ts index 05f1476901..f6b7a26151 100644 --- a/src/renderer/src/services/MemoryProcessor.ts +++ b/src/renderer/src/services/MemoryProcessor.ts @@ -104,7 +104,7 @@ export class MemoryProcessor { if (!memoryConfig.llmApiClient) { throw new Error('No LLM model configured for memory processing') } - const existingMemoriesResult = (cacheService.get(`memory-search-${lastMessageId}`) as MemoryItem[]) || [] + const existingMemoriesResult = cacheService.getCasual(`memory-search-${lastMessageId}`) || [] const existingMemories = existingMemoriesResult.map((memory) => ({ id: memory.id, diff --git a/src/renderer/src/services/ocr/clients/OcrBaseApiClient.ts b/src/renderer/src/services/ocr/clients/OcrBaseApiClient.ts index 7394f7b475..a06262d1da 100644 --- a/src/renderer/src/services/ocr/clients/OcrBaseApiClient.ts +++ b/src/renderer/src/services/ocr/clients/OcrBaseApiClient.ts @@ -27,16 +27,16 @@ export abstract class OcrBaseApiClient { return keys[0] } - const lastUsedKey = cacheService.getShared(keyName) as string | undefined + const lastUsedKey = cacheService.getSharedCasual(keyName) if (lastUsedKey === undefined) { - cacheService.setShared(keyName, keys[0]) + cacheService.setSharedCasual(keyName, keys[0]) return keys[0] } const currentIndex = keys.indexOf(lastUsedKey) const nextIndex = (currentIndex + 1) % keys.length const nextKey = keys[nextIndex] - cacheService.setShared(keyName, nextKey) + cacheService.setSharedCasual(keyName, nextKey) return nextKey } diff --git a/src/renderer/src/store/thunk/messageThunk.ts b/src/renderer/src/store/thunk/messageThunk.ts index 23dd3d23fc..32579e8dab 100644 --- a/src/renderer/src/store/thunk/messageThunk.ts +++ b/src/renderer/src/store/thunk/messageThunk.ts @@ -1097,8 +1097,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 { - cacheService.delete(`web-search-${userMessageToResend.id}`) - cacheService.delete(`knowledge-search-${userMessageToResend.id}`) + cacheService.deleteCasual(`web-search-${userMessageToResend.id}`) + cacheService.deleteCasual(`knowledge-search-${userMessageToResend.id}`) } catch (error) { logger.warn(`Failed to clear keyv cache for message ${userMessageToResend.id}:`, error as Error) }