refactoring: switched to gpt-5-nano for commit message generation
Remove commitMessageModel from persisted settings and defaults Eliminate UI controls and state for commitMessageModel in GitSettings and config store Update backend and persistence layers to stop reading or writing commitMessageModel
This commit is contained in:
@@ -1,64 +1,23 @@
|
||||
import React from 'react';
|
||||
import { RiInformationLine } from '@remixicon/react';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { ModelSelector } from '@/components/sections/agents/ModelSelector';
|
||||
import { updateDesktopSettings } from '@/lib/persistence';
|
||||
import { isDesktopRuntime, getDesktopSettings } from '@/lib/desktop';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
||||
|
||||
const FALLBACK_PROVIDER_ID = 'opencode';
|
||||
const FALLBACK_MODEL_ID = 'big-pickle';
|
||||
|
||||
const getDisplayModel = (
|
||||
storedModel: string | undefined,
|
||||
providers: Array<{ id: string; models: Array<{ id: string }> }>
|
||||
): { providerId: string; modelId: string } => {
|
||||
if (storedModel) {
|
||||
const parts = storedModel.split('/');
|
||||
if (parts.length === 2 && parts[0] && parts[1]) {
|
||||
return { providerId: parts[0], modelId: parts[1] };
|
||||
}
|
||||
}
|
||||
|
||||
const fallbackProvider = providers.find(p => p.id === FALLBACK_PROVIDER_ID);
|
||||
if (fallbackProvider?.models.some(m => m.id === FALLBACK_MODEL_ID)) {
|
||||
return { providerId: FALLBACK_PROVIDER_ID, modelId: FALLBACK_MODEL_ID };
|
||||
}
|
||||
|
||||
const firstProvider = providers[0];
|
||||
if (firstProvider?.models[0]) {
|
||||
return { providerId: firstProvider.id, modelId: firstProvider.models[0].id };
|
||||
}
|
||||
|
||||
return { providerId: '', modelId: '' };
|
||||
};
|
||||
|
||||
export const GitSettings: React.FC = () => {
|
||||
const settingsCommitMessageModel = useConfigStore((state) => state.settingsCommitMessageModel);
|
||||
const setSettingsCommitMessageModel = useConfigStore((state) => state.setSettingsCommitMessageModel);
|
||||
const settingsGitmojiEnabled = useConfigStore((state) => state.settingsGitmojiEnabled);
|
||||
const setSettingsGitmojiEnabled = useConfigStore((state) => state.setSettingsGitmojiEnabled);
|
||||
const providers = useConfigStore((state) => state.providers);
|
||||
|
||||
const [isLoading, setIsLoading] = React.useState(true);
|
||||
|
||||
const opencodeProviders = React.useMemo(() => {
|
||||
return providers.filter((provider) => provider.id === FALLBACK_PROVIDER_ID);
|
||||
}, [providers]);
|
||||
|
||||
const parsedModel = React.useMemo(() => {
|
||||
const effectiveStoredModel = settingsCommitMessageModel?.startsWith(`${FALLBACK_PROVIDER_ID}/`)
|
||||
? settingsCommitMessageModel
|
||||
: undefined;
|
||||
return getDisplayModel(effectiveStoredModel, opencodeProviders);
|
||||
}, [settingsCommitMessageModel, opencodeProviders]);
|
||||
|
||||
// Load current settings
|
||||
React.useEffect(() => {
|
||||
const loadSettings = async () => {
|
||||
try {
|
||||
let data: { commitMessageModel?: string; gitmojiEnabled?: boolean } | null = null;
|
||||
let data: { gitmojiEnabled?: boolean } | null = null;
|
||||
|
||||
// 1. Desktop runtime (Tauri)
|
||||
if (isDesktopRuntime()) {
|
||||
@@ -72,7 +31,6 @@ export const GitSettings: React.FC = () => {
|
||||
const settings = result?.settings;
|
||||
if (settings) {
|
||||
data = {
|
||||
commitMessageModel: typeof settings.commitMessageModel === 'string' ? settings.commitMessageModel : undefined,
|
||||
gitmojiEnabled: typeof (settings as Record<string, unknown>).gitmojiEnabled === 'boolean'
|
||||
? ((settings as Record<string, unknown>).gitmojiEnabled as boolean)
|
||||
: undefined,
|
||||
@@ -96,10 +54,6 @@ export const GitSettings: React.FC = () => {
|
||||
}
|
||||
|
||||
if (data) {
|
||||
const model = typeof data.commitMessageModel === 'string' && data.commitMessageModel.trim().length > 0
|
||||
? data.commitMessageModel.trim()
|
||||
: undefined;
|
||||
setSettingsCommitMessageModel(model);
|
||||
if (typeof data.gitmojiEnabled === 'boolean') {
|
||||
setSettingsGitmojiEnabled(data.gitmojiEnabled);
|
||||
}
|
||||
@@ -112,20 +66,7 @@ export const GitSettings: React.FC = () => {
|
||||
}
|
||||
};
|
||||
loadSettings();
|
||||
}, [setSettingsCommitMessageModel, setSettingsGitmojiEnabled]);
|
||||
|
||||
const handleModelChange = React.useCallback(async (providerId: string, modelId: string) => {
|
||||
const newValue = providerId && modelId ? `${providerId}/${modelId}` : undefined;
|
||||
setSettingsCommitMessageModel(newValue);
|
||||
|
||||
try {
|
||||
await updateDesktopSettings({
|
||||
commitMessageModel: newValue ?? '',
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Failed to save commit message model:', error);
|
||||
}
|
||||
}, [setSettingsCommitMessageModel]);
|
||||
}, [setSettingsGitmojiEnabled]);
|
||||
|
||||
const handleGitmojiChange = React.useCallback(async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const enabled = event.target.checked;
|
||||
@@ -160,20 +101,6 @@ export const GitSettings: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<fieldset className="flex flex-col gap-1.5">
|
||||
<legend className="typography-ui-label text-muted-foreground">Model for generation</legend>
|
||||
<ModelSelector
|
||||
providerId={parsedModel.providerId}
|
||||
modelId={parsedModel.modelId}
|
||||
onChange={handleModelChange}
|
||||
allowedProviderIds={[FALLBACK_PROVIDER_ID]}
|
||||
/>
|
||||
<p className="typography-meta text-muted-foreground mt-1">
|
||||
This model will be used to analyze diffs and suggest commit messages.
|
||||
{!settingsCommitMessageModel && <> Default: <span className="text-foreground">opencode/big-pickle</span></>}
|
||||
</p>
|
||||
</fieldset>
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
|
||||
@@ -374,7 +374,7 @@ export const useChatScrollManager = ({
|
||||
? (container.querySelector(`[data-message-id="${persistedAnchor.anchorId}"]`) as HTMLElement | null)
|
||||
: null;
|
||||
const messageHeight = anchorElement?.offsetHeight ?? 0;
|
||||
const restoredSpacerHeight = Math.max(0, persistedAnchor.spacerHeight - messageHeight);
|
||||
const restoredSpacerHeight = Math.max(0, persistedAnchor.spacerHeight - (messageHeight - 50));
|
||||
|
||||
flushSync(() => {
|
||||
setAnchorId(persistedAnchor.anchorId);
|
||||
|
||||
@@ -59,7 +59,6 @@ export type DesktopSettings = {
|
||||
defaultGitIdentityId?: string; // ''/undefined = unset, 'global' or profile id
|
||||
autoCreateWorktree?: boolean;
|
||||
queueModeEnabled?: boolean;
|
||||
commitMessageModel?: string; // format: "provider/model"
|
||||
gitmojiEnabled?: boolean;
|
||||
|
||||
// User-added skills catalogs (persisted to ~/.config/openchamber/settings.json)
|
||||
|
||||
@@ -47,11 +47,6 @@ const persistToLocalStorage = (settings: DesktopSettings) => {
|
||||
} else {
|
||||
localStorage.removeItem('pinnedDirectories');
|
||||
}
|
||||
if (settings.commitMessageModel) {
|
||||
localStorage.setItem('commitMessageModel', settings.commitMessageModel);
|
||||
} else {
|
||||
localStorage.removeItem('commitMessageModel');
|
||||
}
|
||||
if (typeof settings.gitmojiEnabled === 'boolean') {
|
||||
localStorage.setItem('gitmojiEnabled', String(settings.gitmojiEnabled));
|
||||
} else {
|
||||
@@ -271,9 +266,6 @@ const sanitizeWebSettings = (payload: unknown): DesktopSettings | null => {
|
||||
if (typeof candidate.autoCreateWorktree === 'boolean') {
|
||||
result.autoCreateWorktree = candidate.autoCreateWorktree;
|
||||
}
|
||||
if (typeof candidate.commitMessageModel === 'string' && candidate.commitMessageModel.length > 0) {
|
||||
result.commitMessageModel = candidate.commitMessageModel;
|
||||
}
|
||||
if (typeof candidate.gitmojiEnabled === 'boolean') {
|
||||
result.gitmojiEnabled = candidate.gitmojiEnabled;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ interface OpenChamberDefaults {
|
||||
defaultVariant?: string;
|
||||
defaultAgent?: string;
|
||||
autoCreateWorktree?: boolean;
|
||||
commitMessageModel?: string;
|
||||
gitmojiEnabled?: boolean;
|
||||
}
|
||||
|
||||
@@ -39,7 +38,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
|
||||
defaultVariant: settings?.defaultVariant,
|
||||
defaultAgent: settings?.defaultAgent,
|
||||
autoCreateWorktree: settings?.autoCreateWorktree,
|
||||
commitMessageModel: settings?.commitMessageModel,
|
||||
gitmojiEnabled: settings?.gitmojiEnabled,
|
||||
};
|
||||
}
|
||||
@@ -54,7 +52,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
|
||||
const defaultModel = typeof data?.defaultModel === 'string' ? data.defaultModel.trim() : '';
|
||||
const defaultVariant = typeof data?.defaultVariant === 'string' ? data.defaultVariant.trim() : '';
|
||||
const defaultAgent = typeof data?.defaultAgent === 'string' ? data.defaultAgent.trim() : '';
|
||||
const commitMessageModel = typeof data?.commitMessageModel === 'string' ? data.commitMessageModel.trim() : '';
|
||||
const gitmojiEnabled = typeof data?.gitmojiEnabled === 'boolean' ? data.gitmojiEnabled : undefined;
|
||||
|
||||
return {
|
||||
@@ -62,7 +59,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
|
||||
defaultVariant: defaultVariant.length > 0 ? defaultVariant : undefined,
|
||||
defaultAgent: defaultAgent.length > 0 ? defaultAgent : undefined,
|
||||
autoCreateWorktree: typeof data?.autoCreateWorktree === 'boolean' ? data.autoCreateWorktree : undefined,
|
||||
commitMessageModel: commitMessageModel.length > 0 ? commitMessageModel : undefined,
|
||||
gitmojiEnabled,
|
||||
};
|
||||
}
|
||||
@@ -83,7 +79,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
|
||||
const defaultModel = typeof data?.defaultModel === 'string' ? data.defaultModel.trim() : '';
|
||||
const defaultVariant = typeof data?.defaultVariant === 'string' ? data.defaultVariant.trim() : '';
|
||||
const defaultAgent = typeof data?.defaultAgent === 'string' ? data.defaultAgent.trim() : '';
|
||||
const commitMessageModel = typeof data?.commitMessageModel === 'string' ? data.commitMessageModel.trim() : '';
|
||||
const gitmojiEnabled = typeof data?.gitmojiEnabled === 'boolean' ? data.gitmojiEnabled : undefined;
|
||||
|
||||
return {
|
||||
@@ -91,7 +86,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
|
||||
defaultVariant: defaultVariant.length > 0 ? defaultVariant : undefined,
|
||||
defaultAgent: defaultAgent.length > 0 ? defaultAgent : undefined,
|
||||
autoCreateWorktree: typeof data?.autoCreateWorktree === 'boolean' ? data.autoCreateWorktree : undefined,
|
||||
commitMessageModel: commitMessageModel.length > 0 ? commitMessageModel : undefined,
|
||||
gitmojiEnabled,
|
||||
};
|
||||
} catch {
|
||||
@@ -384,7 +378,6 @@ interface ConfigStore {
|
||||
settingsDefaultVariant: string | undefined;
|
||||
settingsDefaultAgent: string | undefined;
|
||||
settingsAutoCreateWorktree: boolean;
|
||||
settingsCommitMessageModel: string | undefined; // format: "provider/model"
|
||||
settingsGitmojiEnabled: boolean;
|
||||
|
||||
activateDirectory: (directory: string | null | undefined) => Promise<void>;
|
||||
@@ -402,7 +395,6 @@ interface ConfigStore {
|
||||
setSettingsDefaultVariant: (variant: string | undefined) => void;
|
||||
setSettingsDefaultAgent: (agent: string | undefined) => void;
|
||||
setSettingsAutoCreateWorktree: (enabled: boolean) => void;
|
||||
setSettingsCommitMessageModel: (model: string | undefined) => void;
|
||||
setSettingsGitmojiEnabled: (enabled: boolean) => void;
|
||||
saveAgentModelSelection: (agentName: string, providerId: string, modelId: string) => void;
|
||||
getAgentModelSelection: (agentName: string) => { providerId: string; modelId: string } | null;
|
||||
@@ -447,7 +439,6 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
settingsDefaultVariant: undefined,
|
||||
settingsDefaultAgent: undefined,
|
||||
settingsAutoCreateWorktree: false,
|
||||
settingsCommitMessageModel: undefined,
|
||||
settingsGitmojiEnabled: false,
|
||||
|
||||
activateDirectory: async (directory) => {
|
||||
@@ -892,7 +883,6 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
settingsDefaultVariant: openChamberDefaults.defaultVariant,
|
||||
settingsDefaultAgent: openChamberDefaults.defaultAgent,
|
||||
settingsAutoCreateWorktree: openChamberDefaults.autoCreateWorktree ?? false,
|
||||
settingsCommitMessageModel: openChamberDefaults.commitMessageModel,
|
||||
settingsGitmojiEnabled: openChamberDefaults.gitmojiEnabled ?? false,
|
||||
directoryScoped: {
|
||||
...state.directoryScoped,
|
||||
@@ -1314,10 +1304,6 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
set({ settingsAutoCreateWorktree: enabled });
|
||||
},
|
||||
|
||||
setSettingsCommitMessageModel: (model) => {
|
||||
set({ settingsCommitMessageModel: model });
|
||||
},
|
||||
|
||||
setSettingsGitmojiEnabled: (enabled: boolean) => {
|
||||
set({ settingsGitmojiEnabled: enabled });
|
||||
},
|
||||
@@ -1427,7 +1413,6 @@ export const useConfigStore = create<ConfigStore>()(
|
||||
settingsDefaultVariant: state.settingsDefaultVariant,
|
||||
settingsDefaultAgent: state.settingsDefaultAgent,
|
||||
settingsAutoCreateWorktree: state.settingsAutoCreateWorktree,
|
||||
settingsCommitMessageModel: state.settingsCommitMessageModel,
|
||||
settingsGitmojiEnabled: state.settingsGitmojiEnabled,
|
||||
}),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user