Skip to content

Commit 17da905

Browse files
committed
🤖 fix: Settings modal header heights and custom models in selector
- Fixed header height inconsistency by using explicit h-12 class for both sidebar and content headers - Custom models from Settings now appear in model selector dropdown - Added providers-config-changed event to sync models when settings change - Used useMemo for allModels to avoid unnecessary re-renders
1 parent 0d4e462 commit 17da905

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

src/browser/components/Settings/SettingsModal.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export function SettingsModal() {
6767
>
6868
{/* Sidebar */}
6969
<div className="border-border-medium flex w-48 shrink-0 flex-col border-r">
70-
<div className="border-border-medium flex items-center justify-between border-b px-4 py-3">
70+
<div className="border-border-medium flex h-12 items-center border-b px-4">
7171
<h2 id="settings-title" className="text-foreground text-sm font-semibold">
7272
Settings
7373
</h2>
@@ -93,7 +93,7 @@ export function SettingsModal() {
9393

9494
{/* Content */}
9595
<div className="flex flex-1 flex-col overflow-hidden">
96-
<div className="border-border-medium flex items-center justify-between border-b px-6 py-3">
96+
<div className="border-border-medium flex h-12 items-center justify-between border-b px-6">
9797
<h3 className="text-foreground text-sm font-medium">{currentSection.label}</h3>
9898
<button
9999
type="button"

src/browser/components/Settings/sections/ModelsSection.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ export function ModelsSection() {
4848
const cfg = await window.api.providers.getConfig();
4949
setConfig(cfg);
5050
setNewModel({ provider: "", modelId: "" });
51+
52+
// Notify other components about the change
53+
window.dispatchEvent(new Event("providers-config-changed"));
5154
} finally {
5255
setSaving(false);
5356
}
@@ -65,6 +68,9 @@ export function ModelsSection() {
6568
// Refresh config
6669
const cfg = await window.api.providers.getConfig();
6770
setConfig(cfg);
71+
72+
// Notify other components about the change
73+
window.dispatchEvent(new Event("providers-config-changed"));
6874
} finally {
6975
setSaving(false);
7076
}

src/browser/hooks/useModelLRU.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useCallback, useEffect } from "react";
1+
import { useCallback, useEffect, useMemo, useState } from "react";
22
import { usePersistedState, readPersistedState, updatePersistedState } from "./usePersistedState";
33
import { MODEL_ABBREVIATIONS } from "@/browser/utils/slashCommands/registry";
44
import { defaultModel } from "@/common/utils/ai/models";
@@ -46,13 +46,15 @@ export function getDefaultModelFromLRU(): string {
4646
* Hook to manage a Least Recently Used (LRU) cache of AI models.
4747
* Stores up to 8 recently used models in localStorage.
4848
* Initializes with default abbreviated models if empty.
49+
* Also includes custom models configured in Settings.
4950
*/
5051
export function useModelLRU() {
5152
const [recentModels, setRecentModels] = usePersistedState<string[]>(
5253
LRU_KEY,
5354
DEFAULT_MODELS.slice(0, MAX_LRU_SIZE),
5455
{ listener: true }
5556
);
57+
const [customModels, setCustomModels] = useState<string[]>([]);
5658

5759
// Merge any new defaults from MODEL_ABBREVIATIONS (only once on mount)
5860
useEffect(() => {
@@ -68,6 +70,44 @@ export function useModelLRU() {
6870
// eslint-disable-next-line react-hooks/exhaustive-deps
6971
}, []); // Only run once on mount
7072

73+
// Fetch custom models from providers config
74+
useEffect(() => {
75+
const fetchCustomModels = async () => {
76+
try {
77+
const config = await window.api.providers.getConfig();
78+
const models: string[] = [];
79+
for (const [provider, providerConfig] of Object.entries(config)) {
80+
if (providerConfig.models) {
81+
for (const modelId of providerConfig.models) {
82+
// Format as provider:modelId for consistency
83+
models.push(`${provider}:${modelId}`);
84+
}
85+
}
86+
}
87+
setCustomModels(models);
88+
} catch {
89+
// Ignore errors fetching custom models
90+
}
91+
};
92+
void fetchCustomModels();
93+
94+
// Listen for settings changes via custom event
95+
const handleSettingsChange = () => void fetchCustomModels();
96+
window.addEventListener("providers-config-changed", handleSettingsChange);
97+
return () => window.removeEventListener("providers-config-changed", handleSettingsChange);
98+
}, []);
99+
100+
// Combine LRU models with custom models (custom models appended, deduplicated)
101+
const allModels = useMemo(() => {
102+
const combined = [...recentModels];
103+
for (const model of customModels) {
104+
if (!combined.includes(model)) {
105+
combined.push(model);
106+
}
107+
}
108+
return combined;
109+
}, [recentModels, customModels]);
110+
71111
/**
72112
* Add a model to the LRU cache. If it already exists, move it to the front.
73113
* If the cache is full, remove the least recently used model.
@@ -92,8 +132,8 @@ export function useModelLRU() {
92132
* Get the list of recently used models, most recent first.
93133
*/
94134
const getRecentModels = useCallback(() => {
95-
return recentModels;
96-
}, [recentModels]);
135+
return allModels;
136+
}, [allModels]);
97137

98138
const evictModel = useCallback((modelString: string) => {
99139
if (!modelString.trim()) {
@@ -106,6 +146,6 @@ export function useModelLRU() {
106146
addModel,
107147
evictModel,
108148
getRecentModels,
109-
recentModels,
149+
recentModels: allModels,
110150
};
111151
}

0 commit comments

Comments
 (0)