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.
This commit is contained in:
fullex 2025-12-09 13:02:39 +08:00
parent 361aa87838
commit 1139d8d57a
22 changed files with 258 additions and 112 deletions

View File

@ -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': [],

View File

@ -175,16 +175,16 @@ export abstract class BaseApiClient<
return keys[0]
}
const lastUsedKey = cacheService.getShared(keyName) as string | undefined
const lastUsedKey = cacheService.getSharedCasual<string>(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<MemoryItem[]>(`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<WebSearchResponse>(`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<KnowledgeReference[]>(`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
}

View File

@ -44,7 +44,7 @@ const PopupContainer: React.FC<Props> = ({ 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<Props> = ({ 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<Props> = ({ 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)

View File

@ -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<K extends UseCacheKey>(key: K): UseCacheSchema[K]
get<T>(key: Exclude<string, UseCacheKey>): T | undefined
get(key: string): any {
get<K extends UseCacheKey>(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<T>(key: Exclude<string, UseCacheKey>): 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<K extends UseCacheKey>(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<K extends UseCacheKey>(key: K, value: UseCacheSchema[K]): void
set<T>(key: Exclude<string, UseCacheKey>, value: T, ttl?: number): void
set(key: string, value: any, ttl?: number): void {
setCasual<T>(key: Exclude<string, UseCacheKey>, 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<K extends UseCacheKey>(key: K): boolean {
return this.hasInternal(key)
}
has<K extends UseCacheKey>(key: K): boolean
has(key: Exclude<string, UseCacheKey>): 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<string, UseCacheKey>): 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<K extends UseCacheKey>(key: K): boolean
delete(key: Exclude<string, UseCacheKey>): boolean
delete(key: string): boolean {
delete<K extends UseCacheKey>(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<string, UseCacheKey>): 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<K extends UseCacheKey>(key: K): boolean
hasTTL(key: Exclude<string, UseCacheKey>): boolean
hasTTL(key: string): boolean {
hasTTL<K extends UseCacheKey>(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<K extends UseSharedCacheKey>(key: K): boolean
hasSharedTTL(key: Exclude<string, UseSharedCacheKey>): boolean
hasSharedTTL(key: string): boolean {
hasTTLCasual(key: Exclude<string, UseCacheKey>): 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<K extends UseSharedCacheKey>(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<string, UseSharedCacheKey>): 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<K extends UseSharedCacheKey>(key: K): UseSharedCacheSchema[K]
getShared<T>(key: Exclude<string, UseSharedCacheKey>): T | undefined
getShared(key: string): any {
getShared<K extends UseSharedCacheKey>(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<T>(key: Exclude<string, UseSharedCacheKey>): 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<K extends UseSharedCacheKey>(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<K extends UseSharedCacheKey>(key: K, value: UseSharedCacheSchema[K]): void
setShared<T>(key: Exclude<string, UseSharedCacheKey>, value: T, ttl?: number): void
setShared(key: string, value: any, ttl?: number): void {
setSharedCasual<T>(key: Exclude<string, UseSharedCacheKey>, 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<K extends UseSharedCacheKey>(key: K): boolean
hasShared(key: Exclude<string, UseSharedCacheKey>): boolean
hasShared(key: string): boolean {
hasShared<K extends UseSharedCacheKey>(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<string, UseSharedCacheKey>): 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<K extends UseSharedCacheKey>(key: K): boolean
deleteShared(key: Exclude<string, UseSharedCacheKey>): boolean
deleteShared(key: string): boolean {
deleteShared<K extends UseSharedCacheKey>(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<string, UseSharedCacheKey>): 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`)

View File

@ -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<TopicCache>(`topic:${id}`, topicData)
const topic = cacheService.getCasual<TopicCache>(`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<WindowState>(`window:${windowId}`, state)
const state = cacheService.getSharedCasual<WindowState>(`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

View File

@ -44,8 +44,8 @@ export function useCache<K extends UseCacheKey>(
*/
const value = useSyncExternalStore(
useCallback((callback) => cacheService.subscribe(key, callback), [key]),
useCallback(() => cacheService.get<UseCacheSchema[K]>(key), [key]),
useCallback(() => cacheService.get<UseCacheSchema[K]>(key), [key]) // SSR snapshot
useCallback(() => cacheService.get(key), [key]),
useCallback(() => cacheService.get(key), [key]) // SSR snapshot
)
/**
@ -131,8 +131,8 @@ export function useSharedCache<K extends UseSharedCacheKey>(
*/
const value = useSyncExternalStore(
useCallback((callback) => cacheService.subscribe(key, callback), [key]),
useCallback(() => cacheService.getShared<UseSharedCacheSchema[K]>(key), [key]),
useCallback(() => cacheService.getShared<UseSharedCacheSchema[K]>(key), [key]) // SSR snapshot
useCallback(() => cacheService.getShared(key), [key]),
useCallback(() => cacheService.getShared(key), [key]) // SSR snapshot
)
/**

View File

@ -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)
})
}, [])

View File

@ -29,7 +29,7 @@ export function getModel(id?: string, providerId?: string) {
}
export function modelGenerating() {
const generating = cacheService.get<boolean>('generating') ?? false
const generating = cacheService.get('chat.generating') ?? false
if (generating) {
window.toast.warning(i18n.t('message.switch.disabled'))

View File

@ -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<number>(scrollKey) || 0 })
scroll()
setTimeoutTimer('scrollEffect', scroll, 50)
}, [scrollKey, setTimeoutTimer])

View File

@ -82,9 +82,9 @@ export async function getTopicById(topicId: string) {
*
*/
export const startTopicRenaming = (topicId: string) => {
const currentIds = cacheService.get<string[]>('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<string[]>('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<string[]>('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<string[]>('newlyRenamedTopics') ?? []
const current = cacheService.get('topic.newly_renamed') ?? []
cacheService.set(
'newlyRenamedTopics',
'topic.newly_renamed',
current.filter((id) => id !== topicId)
)
}, 700)

View File

@ -169,8 +169,8 @@ const AgentSessionInputbarInner: FC<InnerProps> = ({ assistant, agentId, session
setText,
isEmpty: inputEmpty
} = useInputText({
initialValue: cacheService.get<string>(draftCacheKey) ?? '',
onChange: (value) => cacheService.set(draftCacheKey, value, DRAFT_CACHE_TTL)
initialValue: cacheService.getCasual<string>(draftCacheKey) ?? '',
onChange: (value) => cacheService.setCasual(draftCacheKey, value, DRAFT_CACHE_TTL)
})
const {
textareaRef,

View File

@ -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<Model[]>(getMentionedModelsCacheKey(assistantId))
const cached = cacheService.getCasual<Model[]>(getMentionedModelsCacheKey(assistantId))
if (!Array.isArray(cached)) return []
return cached.filter((model) => model?.id && model?.name)
}
@ -135,8 +135,8 @@ const InputbarInner: FC<InputbarInnerProps> = ({ assistant: initialAssistant, se
const { setCouldAddImageFile } = useInputbarToolsInternalDispatch()
const { text, setText } = useInputText({
initialValue: cacheService.get<string>(INPUTBAR_DRAFT_CACHE_KEY) ?? '',
onChange: (value) => cacheService.set(INPUTBAR_DRAFT_CACHE_KEY, value, DRAFT_CACHE_TTL)
initialValue: cacheService.getCasual<string>(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<InputbarInnerProps> = ({ 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(() => {

View File

@ -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':

View File

@ -61,7 +61,7 @@ export class TokenFluxService {
const cacheKey = `tokenflux_models_${this.apiHost}`
// Check cache first
const cachedModels = cacheService.get<TokenFluxModel[]>(cacheKey)
const cachedModels = cacheService.getCasual<TokenFluxModel[]>(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
}

View File

@ -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<boolean>('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)
}

View File

@ -28,7 +28,7 @@ export const getAgentsFromSystemAgents = (systemAgents: any) => {
export function useSystemAssistantPresets() {
const { defaultAgent: defaultPreset } = useSettings()
const [presets, setPresets] = useState<AssistantPreset[]>([])
const resourcesPath = cacheService.get('resourcesPath') ?? ''
const resourcesPath = cacheService.get('app.path.resources') ?? ''
const { agentssubscribeUrl } = store.getState().settings
const { i18n } = useTranslation()
const currentLanguage = i18n.language

View File

@ -39,16 +39,16 @@ export default abstract class BaseWebSearchProvider {
return keys[0]
}
const lastUsedKey = cacheService.getShared(keyName) as string | undefined
const lastUsedKey = cacheService.getSharedCasual<string>(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
}

View File

@ -468,9 +468,9 @@ function getRotatedApiKey(provider: Provider): string {
return keys[0]
}
const lastUsedKey = cacheService.get(keyName) as string
const lastUsedKey = cacheService.getCasual<string>(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
}

View File

@ -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
}

View File

@ -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<MemoryItem[]>(`memory-search-${lastMessageId}`) || []
const existingMemories = existingMemoriesResult.map((memory) => ({
id: memory.id,

View File

@ -27,16 +27,16 @@ export abstract class OcrBaseApiClient {
return keys[0]
}
const lastUsedKey = cacheService.getShared(keyName) as string | undefined
const lastUsedKey = cacheService.getSharedCasual<string>(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
}

View File

@ -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)
}