refactor: move summarization model settings to notifications

- Remove Utility Model controls from Session Defaults and restore that section’s original scope.
- Add Zen-based Summarization Model selector to Notifications under AI Summarization.
- Keep config resolution aligned with zenModel-only utility behavior in useConfigStore and git API flow.
This commit is contained in:
Bohdan Triapitsyn
2026-02-24 16:19:39 +02:00
parent 100d6d33a1
commit 2f3209bd65
4 changed files with 150 additions and 213 deletions
+10 -85
View File
@@ -28,8 +28,6 @@ interface OpenChamberDefaults {
autoCreateWorktree?: boolean;
gitmojiEnabled?: boolean;
zenModel?: string;
gitProviderId?: string;
gitModelId?: string;
}
const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
@@ -46,8 +44,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
const defaultAgent = typeof data?.defaultAgent === 'string' ? data.defaultAgent.trim() : '';
const gitmojiEnabled = typeof data?.gitmojiEnabled === 'boolean' ? data.gitmojiEnabled : undefined;
const zenModel = typeof data?.zenModel === 'string' ? data.zenModel.trim() : '';
const gitProviderId = typeof data?.gitProviderId === 'string' ? data.gitProviderId.trim() : '';
const gitModelId = typeof data?.gitModelId === 'string' ? data.gitModelId.trim() : '';
return {
defaultModel: defaultModel.length > 0 ? defaultModel : undefined,
@@ -56,8 +52,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
autoCreateWorktree: typeof data?.autoCreateWorktree === 'boolean' ? data.autoCreateWorktree : undefined,
gitmojiEnabled,
zenModel: zenModel.length > 0 ? zenModel : undefined,
gitProviderId: gitProviderId.length > 0 ? gitProviderId : undefined,
gitModelId: gitModelId.length > 0 ? gitModelId : undefined,
};
}
} catch {
@@ -79,8 +73,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
const defaultAgent = typeof data?.defaultAgent === 'string' ? data.defaultAgent.trim() : '';
const gitmojiEnabled = typeof data?.gitmojiEnabled === 'boolean' ? data.gitmojiEnabled : undefined;
const zenModel = typeof data?.zenModel === 'string' ? data.zenModel.trim() : '';
const gitProviderId = typeof data?.gitProviderId === 'string' ? data.gitProviderId.trim() : '';
const gitModelId = typeof data?.gitModelId === 'string' ? data.gitModelId.trim() : '';
return {
defaultModel: defaultModel.length > 0 ? defaultModel : undefined,
@@ -89,8 +81,6 @@ const fetchOpenChamberDefaults = async (): Promise<OpenChamberDefaults> => {
autoCreateWorktree: typeof data?.autoCreateWorktree === 'boolean' ? data.autoCreateWorktree : undefined,
gitmojiEnabled,
zenModel: zenModel.length > 0 ? zenModel : undefined,
gitProviderId: gitProviderId.length > 0 ? gitProviderId : undefined,
gitModelId: gitModelId.length > 0 ? gitModelId : undefined,
};
} catch {
return {};
@@ -139,17 +129,11 @@ const hasProviderModel = (
const resolveGitGenerationModelSelection = ({
providers,
settingsGitProviderId,
settingsGitModelId,
settingsZenModel,
}: {
providers: ProviderWithModelList[];
settingsGitProviderId?: string;
settingsGitModelId?: string;
settingsZenModel?: string;
}): GitModelSelection | null => {
const gitProviderId = normalizeOptionalString(settingsGitProviderId);
const gitModelId = normalizeOptionalString(settingsGitModelId);
const zenModel = normalizeOptionalString(settingsZenModel);
if (!Array.isArray(providers) || providers.length === 0) {
@@ -159,10 +143,6 @@ const resolveGitGenerationModelSelection = ({
return null;
}
if (gitProviderId && gitModelId && hasProviderModel(providers, gitProviderId, gitModelId)) {
return { providerId: gitProviderId, modelId: gitModelId };
}
if (zenModel && hasProviderModel(providers, GIT_UTILITY_PROVIDER_ID, zenModel)) {
return { providerId: GIT_UTILITY_PROVIDER_ID, modelId: zenModel };
}
@@ -180,12 +160,6 @@ const resolveGitGenerationModelSelection = ({
}
}
const firstProvider = providers.find((provider) => provider.models.length > 0);
const firstModelId = normalizeOptionalString(firstProvider?.models[0]?.id);
if (firstProvider?.id && firstModelId) {
return { providerId: firstProvider.id, modelId: firstModelId };
}
return null;
};
@@ -458,8 +432,6 @@ interface ConfigStore {
settingsAutoCreateWorktree: boolean;
settingsGitmojiEnabled: boolean;
settingsZenModel: string | undefined;
settingsGitProviderId: string | undefined;
settingsGitModelId: string | undefined;
// Voice provider preference ('browser', 'openai', or 'say' for macOS)
voiceProvider: 'browser' | 'openai' | 'say';
setVoiceProvider: (provider: 'browser' | 'openai' | 'say') => void;
@@ -509,8 +481,6 @@ interface ConfigStore {
setSettingsAutoCreateWorktree: (enabled: boolean) => void;
setSettingsGitmojiEnabled: (enabled: boolean) => void;
setSettingsZenModel: (model: string | undefined) => void;
setSettingsGitProviderId: (providerId: string | undefined) => void;
setSettingsGitModelId: (modelId: string | undefined) => void;
getResolvedGitGenerationModel: () => { providerId: string; modelId: string } | null;
saveAgentModelSelection: (agentName: string, providerId: string, modelId: string) => void;
getAgentModelSelection: (agentName: string) => { providerId: string; modelId: string } | null;
@@ -557,8 +527,6 @@ export const useConfigStore = create<ConfigStore>()(
settingsAutoCreateWorktree: false,
settingsGitmojiEnabled: false,
settingsZenModel: undefined,
settingsGitProviderId: undefined,
settingsGitModelId: undefined,
// Voice provider preference - load from localStorage or default to 'browser'
voiceProvider: (() => {
if (typeof window !== 'undefined') {
@@ -1100,35 +1068,23 @@ export const useConfigStore = create<ConfigStore>()(
? get().providers
: (get().directoryScoped[directoryKey]?.providers ?? []);
const existingGitProviderId = normalizeOptionalString(get().settingsGitProviderId);
const existingGitModelId = normalizeOptionalString(get().settingsGitModelId);
const existingZenModel = normalizeOptionalString(get().settingsZenModel);
const defaultGitProviderId = normalizeOptionalString(openChamberDefaults.gitProviderId);
const defaultGitModelId = normalizeOptionalString(openChamberDefaults.gitModelId);
const defaultZenModel = normalizeOptionalString(openChamberDefaults.zenModel);
const resolvedExistingGitSelection = resolveGitGenerationModelSelection({
providers,
settingsGitProviderId: existingGitProviderId,
settingsGitModelId: existingGitModelId,
settingsZenModel: existingZenModel,
});
const resolvedDefaultGitSelection = resolveGitGenerationModelSelection({
providers,
settingsGitProviderId: defaultGitProviderId,
settingsGitModelId: defaultGitModelId,
settingsZenModel: defaultZenModel,
});
const resolvedGitSelection = resolvedExistingGitSelection || resolvedDefaultGitSelection;
const resolvedGitProviderId = resolvedGitSelection?.providerId;
const resolvedGitModelId = resolvedGitSelection?.modelId;
const resolvedZenModel =
resolvedGitProviderId === GIT_UTILITY_PROVIDER_ID && resolvedGitModelId
? resolvedGitModelId
: (defaultZenModel || existingZenModel);
const resolvedZenModel = resolvedGitModelId || defaultZenModel || existingZenModel;
set((state) => {
const baseSnapshot: DirectoryScopedConfig = state.directoryScoped[directoryKey] ?? {
@@ -1155,8 +1111,6 @@ export const useConfigStore = create<ConfigStore>()(
settingsAutoCreateWorktree: openChamberDefaults.autoCreateWorktree ?? false,
settingsGitmojiEnabled: openChamberDefaults.gitmojiEnabled ?? false,
settingsZenModel: resolvedZenModel,
settingsGitProviderId: resolvedGitProviderId,
settingsGitModelId: resolvedGitModelId,
directoryScoped: {
...state.directoryScoped,
[directoryKey]: nextSnapshot,
@@ -1170,33 +1124,16 @@ export const useConfigStore = create<ConfigStore>()(
return nextState;
});
const shouldPersistResolvedGitSelection =
!!resolvedGitProviderId &&
!!resolvedGitModelId &&
(
defaultGitProviderId !== resolvedGitProviderId ||
defaultGitModelId !== resolvedGitModelId ||
(
resolvedGitProviderId === GIT_UTILITY_PROVIDER_ID &&
resolvedZenModel !== defaultZenModel
)
);
const shouldPersistResolvedZenModel =
!!resolvedZenModel &&
resolvedZenModel !== defaultZenModel;
if (shouldPersistResolvedGitSelection && resolvedGitProviderId && resolvedGitModelId) {
const gitSettingsUpdate: {
gitProviderId: string;
gitModelId: string;
zenModel?: string;
} = {
gitProviderId: resolvedGitProviderId,
gitModelId: resolvedGitModelId,
};
if (resolvedGitProviderId === GIT_UTILITY_PROVIDER_ID && resolvedZenModel) {
gitSettingsUpdate.zenModel = resolvedZenModel;
}
updateDesktopSettings(gitSettingsUpdate).catch(() => {
if (shouldPersistResolvedZenModel && resolvedZenModel) {
updateDesktopSettings({
zenModel: resolvedZenModel,
gitProviderId: '',
gitModelId: '',
}).catch(() => {
// Ignore errors - best effort cleanup
});
}
@@ -1616,20 +1553,10 @@ export const useConfigStore = create<ConfigStore>()(
set({ settingsZenModel: model });
},
setSettingsGitProviderId: (providerId: string | undefined) => {
set({ settingsGitProviderId: providerId });
},
setSettingsGitModelId: (modelId: string | undefined) => {
set({ settingsGitModelId: modelId });
},
getResolvedGitGenerationModel: () => {
const state = get();
return resolveGitGenerationModelSelection({
providers: state.providers,
settingsGitProviderId: state.settingsGitProviderId,
settingsGitModelId: state.settingsGitModelId,
settingsZenModel: state.settingsZenModel,
});
},
@@ -1844,8 +1771,6 @@ export const useConfigStore = create<ConfigStore>()(
settingsAutoCreateWorktree: state.settingsAutoCreateWorktree,
settingsGitmojiEnabled: state.settingsGitmojiEnabled,
settingsZenModel: state.settingsZenModel,
settingsGitProviderId: state.settingsGitProviderId,
settingsGitModelId: state.settingsGitModelId,
speechRate: state.speechRate,
speechPitch: state.speechPitch,
speechVolume: state.speechVolume,