|
1 | 1 | import { useCallback, useEffect } from "react"; |
2 | | -import { usePersistedState } from "./usePersistedState"; |
| 2 | +import { usePersistedState, readPersistedState } from "./usePersistedState"; |
3 | 3 | import { MODEL_ABBREVIATIONS } from "@/utils/slashCommands/registry"; |
| 4 | +import { defaultModel } from "@/utils/ai/models"; |
4 | 5 |
|
5 | 6 | const MAX_LRU_SIZE = 8; |
6 | 7 | const LRU_KEY = "model-lru"; |
7 | 8 |
|
8 | 9 | // Default models from abbreviations (for initial LRU population) |
9 | 10 | const DEFAULT_MODELS = Object.values(MODEL_ABBREVIATIONS); |
10 | 11 |
|
| 12 | +/** |
| 13 | + * Get the default model from LRU (non-hook version for use outside React) |
| 14 | + * This is the ONLY place that reads from LRU outside of the hook. |
| 15 | + * |
| 16 | + * @returns The most recently used model, or defaultModel if LRU is empty |
| 17 | + */ |
| 18 | +export function getDefaultModelFromLRU(): string { |
| 19 | + const lru = readPersistedState<string[]>(LRU_KEY, DEFAULT_MODELS.slice(0, MAX_LRU_SIZE)); |
| 20 | + return lru[0] ?? defaultModel; |
| 21 | +} |
| 22 | + |
11 | 23 | /** |
12 | 24 | * Hook to manage a Least Recently Used (LRU) cache of AI models. |
13 | 25 | * Stores up to 8 recently used models in localStorage. |
14 | 26 | * Initializes with default abbreviated models if empty. |
15 | 27 | */ |
16 | 28 | export function useModelLRU() { |
17 | | - const [recentModels, setRecentModels] = usePersistedState<string[]>(LRU_KEY, []); |
| 29 | + const [recentModels, setRecentModels] = usePersistedState<string[]>( |
| 30 | + LRU_KEY, |
| 31 | + DEFAULT_MODELS.slice(0, MAX_LRU_SIZE) |
| 32 | + ); |
18 | 33 |
|
19 | | - // Ensure default models are always present in the LRU (only once on mount) |
| 34 | + // Merge any new defaults from MODEL_ABBREVIATIONS (only once on mount) |
20 | 35 | useEffect(() => { |
21 | 36 | setRecentModels((prev) => { |
22 | | - // If empty, just use defaults |
23 | | - if (prev.length === 0) { |
24 | | - return DEFAULT_MODELS.slice(0, MAX_LRU_SIZE); |
25 | | - } |
26 | | - |
27 | | - // If we have some models, merge with defaults (keeping existing order, adding missing defaults at end) |
28 | 37 | const merged = [...prev]; |
29 | 38 | for (const defaultModel of DEFAULT_MODELS) { |
30 | 39 | if (!merged.includes(defaultModel)) { |
31 | 40 | merged.push(defaultModel); |
32 | 41 | } |
33 | 42 | } |
34 | | - |
35 | | - // Limit to MAX_LRU_SIZE |
36 | 43 | return merged.slice(0, MAX_LRU_SIZE); |
37 | 44 | }); |
38 | 45 | // eslint-disable-next-line react-hooks/exhaustive-deps |
|
0 commit comments