feat: Display default model in dropdowns and consolidate Git settings menu (#135)

* types: add commitMessageModel to DesktopSettings

* store: add commitMessageModel state and fetch logic

* lib: implement persistence for commitMessageModel setting

* ui: create GitSettings component for model selection

* ui: add Git section to OpenChamber settings sidebar

* ui: register GitSectionContent in OpenChamberPage

* server: use commitMessageModel setting for AI generation

* tauri: sanitize commitMessageModel in settings commands

* tauri: use commitMessageModel for desktop message generation

* build: update lockfile and package configuration

* refactor(openchamber): improve default model parsing with fallback logic

* feat(openchamber): improve model selection fallback logic

* refactor: move worktree settings into git section

* refactor(openchamber): merge worktree into git section

* refactor[worktree]: simplify empty state layout

* revert: rollback bun.lock and package.json to main

* feat(git): restrict model selection to OpenCode provider
This commit is contained in:
Nelson Pires
2026-01-14 00:21:16 +02:00
committed by GitHub
parent fbb058ed97
commit 279efb28b3
12 changed files with 319 additions and 49 deletions
@@ -25,6 +25,7 @@ interface ModelSelectorProps {
modelId: string;
onChange: (providerId: string, modelId: string) => void;
className?: string;
allowedProviderIds?: string[];
}
const COMPACT_NUMBER_FORMATTER = new Intl.NumberFormat('en-US', {
@@ -49,7 +50,8 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
providerId,
modelId,
onChange,
className
className,
allowedProviderIds
}) => {
const { providers, modelsMetadata } = useConfigStore();
const isMobile = useUIStore(state => state.isMobile);
@@ -65,6 +67,20 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
const [selectedIndex, setSelectedIndex] = React.useState(0);
const itemRefs = React.useRef<(HTMLDivElement | null)[]>([]);
const allowedProviderSet = React.useMemo(() => {
if (!Array.isArray(allowedProviderIds) || allowedProviderIds.length === 0) {
return null;
}
return new Set(allowedProviderIds);
}, [allowedProviderIds]);
const visibleProviders = React.useMemo(() => {
if (!allowedProviderSet) {
return providers;
}
return providers.filter((provider) => allowedProviderSet.has(String(provider.id)));
}, [providers, allowedProviderSet]);
const closeMobilePanel = () => setIsMobilePanelOpen(false);
const toggleMobileProviderExpansion = (provId: string) => {
setExpandedMobileProviders(prev => {
@@ -188,6 +204,9 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
// Filter data for desktop dropdown
const filteredFavorites = favoriteModelsList.filter(({ model, providerID }) => {
if (allowedProviderSet && !allowedProviderSet.has(providerID)) {
return false;
}
const provider = providers.find(p => p.id === providerID);
const providerName = provider?.name || providerID;
const modelName = getModelDisplayName(model);
@@ -195,13 +214,16 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
});
const filteredRecents = recentModelsList.filter(({ model, providerID }) => {
if (allowedProviderSet && !allowedProviderSet.has(providerID)) {
return false;
}
const provider = providers.find(p => p.id === providerID);
const providerName = provider?.name || providerID;
const modelName = getModelDisplayName(model);
return filterByQuery(modelName, providerName);
});
const filteredProviders = providers
const filteredProviders = visibleProviders
.map((provider) => {
const providerModels = Array.isArray(provider.models) ? provider.models : [];
const filteredModels = providerModels.filter((model: ProviderModel) => {
@@ -332,7 +354,7 @@ export const ModelSelector: React.FC<ModelSelectorProps> = ({
</div>
)}
{providers.map((provider) => {
{visibleProviders.map((provider) => {
const providerModels = Array.isArray(provider.models) ? provider.models : [];
if (providerModels.length === 0) return null;