Unify utility model settings and align git generation (#486)
* refactor(api): extend git generation payload types * refactor(settings): add git provider model fields * feat(config): persist git provider model defaults * feat(git-api): send provider and model ids * fix(git-api): forward generation options in runtime * feat(git-view): use configured model for commit generation * feat(git-view): pass configured model for PR generation * feat(vscode): forward model selection in git bridge payload * feat(vscode): align PR generation with session model flow * feat(web): resolve and generate git text with provider model * refactor(settings): unify utility model picker across providers * chore(settings): rename sidebar item to utility model * fix(git-model): validate and auto-heal stale utility selections --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
8647e0c1a4
commit
7a11867a19
@@ -12,10 +12,8 @@ import { useUIStore } from '@/stores/useUIStore';
|
||||
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
|
||||
import { getModifierLabel, cn } from '@/lib/utils';
|
||||
|
||||
interface ZenModel {
|
||||
id: string;
|
||||
owned_by?: string;
|
||||
}
|
||||
const UTILITY_PROVIDER_ID = 'zen';
|
||||
const UTILITY_PREFERRED_MODEL_ID = 'big-pickle';
|
||||
|
||||
const getDisplayModel = (
|
||||
storedModel: string | undefined
|
||||
@@ -26,9 +24,46 @@ const getDisplayModel = (
|
||||
return { providerId: parts[0], modelId: parts[1] };
|
||||
}
|
||||
}
|
||||
|
||||
// Return empty values when no model is explicitly set
|
||||
// This allows showing "Not selected" instead of a fallback
|
||||
|
||||
return { providerId: '', modelId: '' };
|
||||
};
|
||||
|
||||
const getUtilityDisplayModel = (
|
||||
storedGitProviderId: string | undefined,
|
||||
storedGitModelId: string | undefined,
|
||||
zenModel: string | undefined,
|
||||
providers: Array<{ id: string; models: Array<{ id: string }> }>
|
||||
): { providerId: string; modelId: string } => {
|
||||
if (storedGitProviderId && storedGitModelId) {
|
||||
const provider = providers.find((p) => p.id === storedGitProviderId);
|
||||
if (provider?.models.some((m) => m.id === storedGitModelId)) {
|
||||
return { providerId: storedGitProviderId, modelId: storedGitModelId };
|
||||
}
|
||||
}
|
||||
|
||||
const utilityProvider = providers.find((p) => p.id === UTILITY_PROVIDER_ID);
|
||||
if (zenModel && utilityProvider?.models.some((m) => m.id === zenModel)) {
|
||||
return { providerId: UTILITY_PROVIDER_ID, modelId: zenModel };
|
||||
}
|
||||
|
||||
const preferredUtilityModel = utilityProvider?.models.find((m) => m.id === UTILITY_PREFERRED_MODEL_ID);
|
||||
if (preferredUtilityModel) {
|
||||
return { providerId: UTILITY_PROVIDER_ID, modelId: preferredUtilityModel.id };
|
||||
}
|
||||
|
||||
if (utilityProvider?.models.length) {
|
||||
const randomIndex = Math.floor(Math.random() * utilityProvider.models.length);
|
||||
const randomModel = utilityProvider.models[randomIndex];
|
||||
if (randomModel?.id) {
|
||||
return { providerId: UTILITY_PROVIDER_ID, modelId: randomModel.id };
|
||||
}
|
||||
}
|
||||
|
||||
const firstProvider = providers[0];
|
||||
if (firstProvider?.models[0]) {
|
||||
return { providerId: firstProvider.id, modelId: firstProvider.models[0].id };
|
||||
}
|
||||
|
||||
return { providerId: '', modelId: '' };
|
||||
};
|
||||
|
||||
@@ -44,6 +79,10 @@ export const DefaultsSettings: React.FC = () => {
|
||||
const setSettingsAutoCreateWorktree = useConfigStore((state) => state.setSettingsAutoCreateWorktree);
|
||||
const settingsZenModel = useConfigStore((state) => state.settingsZenModel);
|
||||
const setSettingsZenModel = useConfigStore((state) => state.setSettingsZenModel);
|
||||
const settingsGitProviderId = useConfigStore((state) => state.settingsGitProviderId);
|
||||
const settingsGitModelId = useConfigStore((state) => state.settingsGitModelId);
|
||||
const setSettingsGitProviderId = useConfigStore((state) => state.setSettingsGitProviderId);
|
||||
const setSettingsGitModelId = useConfigStore((state) => state.setSettingsGitModelId);
|
||||
const showDeletionDialog = useUIStore((state) => state.showDeletionDialog);
|
||||
const setShowDeletionDialog = useUIStore((state) => state.setShowDeletionDialog);
|
||||
const providers = useConfigStore((state) => state.providers);
|
||||
@@ -52,54 +91,25 @@ export const DefaultsSettings: React.FC = () => {
|
||||
const [defaultVariant, setDefaultVariant] = React.useState<string | undefined>();
|
||||
const [defaultAgent, setDefaultAgent] = React.useState<string | undefined>();
|
||||
const [isLoading, setIsLoading] = React.useState(true);
|
||||
const [zenModels, setZenModels] = React.useState<ZenModel[]>([]);
|
||||
const [zenModelsLoading, setZenModelsLoading] = React.useState(true);
|
||||
|
||||
const parsedModel = React.useMemo(() => {
|
||||
return getDisplayModel(defaultModel);
|
||||
}, [defaultModel]);
|
||||
|
||||
const parsedModel = React.useMemo(() => getDisplayModel(defaultModel), [defaultModel]);
|
||||
const utilityDisplayModel = React.useMemo(() => {
|
||||
return getUtilityDisplayModel(settingsGitProviderId, settingsGitModelId, settingsZenModel, providers);
|
||||
}, [settingsGitProviderId, settingsGitModelId, settingsZenModel, providers]);
|
||||
const isVSCode = React.useMemo(() => isVSCodeRuntime(), []);
|
||||
|
||||
// Load zen models list
|
||||
React.useEffect(() => {
|
||||
const loadZenModels = async () => {
|
||||
try {
|
||||
const response = await fetch('/api/zen/models', {
|
||||
method: 'GET',
|
||||
headers: { Accept: 'application/json' },
|
||||
});
|
||||
if (response.ok) {
|
||||
const data = await response.json() as { models?: ZenModel[] };
|
||||
if (Array.isArray(data?.models)) {
|
||||
setZenModels(data.models);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load zen models:', error);
|
||||
} finally {
|
||||
setZenModelsLoading(false);
|
||||
}
|
||||
};
|
||||
loadZenModels();
|
||||
}, []);
|
||||
|
||||
// Resolve which zen model to display as selected
|
||||
const selectedZenModel = React.useMemo(() => {
|
||||
if (settingsZenModel && zenModels.some((m) => m.id === settingsZenModel)) {
|
||||
return settingsZenModel;
|
||||
}
|
||||
// Default to first free model in the list
|
||||
return zenModels[0]?.id ?? '';
|
||||
}, [settingsZenModel, zenModels]);
|
||||
|
||||
// Load current settings
|
||||
React.useEffect(() => {
|
||||
const loadSettings = async () => {
|
||||
try {
|
||||
let data: { defaultModel?: string; defaultVariant?: string; defaultAgent?: string; zenModel?: string } | null = null;
|
||||
let data: {
|
||||
defaultModel?: string;
|
||||
defaultVariant?: string;
|
||||
defaultAgent?: string;
|
||||
zenModel?: string;
|
||||
gitProviderId?: string;
|
||||
gitModelId?: string;
|
||||
} | null = null;
|
||||
|
||||
// 1. Runtime settings API (VSCode)
|
||||
if (!data) {
|
||||
const runtimeSettings = getRegisteredRuntimeAPIs()?.settings;
|
||||
if (runtimeSettings) {
|
||||
@@ -109,9 +119,23 @@ export const DefaultsSettings: React.FC = () => {
|
||||
if (settings) {
|
||||
data = {
|
||||
defaultModel: typeof settings.defaultModel === 'string' ? settings.defaultModel : undefined,
|
||||
defaultVariant: typeof (settings as Record<string, unknown>).defaultVariant === 'string' ? ((settings as Record<string, unknown>).defaultVariant as string) : undefined,
|
||||
defaultVariant:
|
||||
typeof (settings as Record<string, unknown>).defaultVariant === 'string'
|
||||
? ((settings as Record<string, unknown>).defaultVariant as string)
|
||||
: undefined,
|
||||
defaultAgent: typeof settings.defaultAgent === 'string' ? settings.defaultAgent : undefined,
|
||||
zenModel: typeof (settings as Record<string, unknown>).zenModel === 'string' ? ((settings as Record<string, unknown>).zenModel as string) : undefined,
|
||||
zenModel:
|
||||
typeof (settings as Record<string, unknown>).zenModel === 'string'
|
||||
? ((settings as Record<string, unknown>).zenModel as string)
|
||||
: undefined,
|
||||
gitProviderId:
|
||||
typeof (settings as Record<string, unknown>).gitProviderId === 'string'
|
||||
? ((settings as Record<string, unknown>).gitProviderId as string)
|
||||
: undefined,
|
||||
gitModelId:
|
||||
typeof (settings as Record<string, unknown>).gitModelId === 'string'
|
||||
? ((settings as Record<string, unknown>).gitModelId as string)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
@@ -120,7 +144,6 @@ export const DefaultsSettings: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fetch API (Web/server)
|
||||
if (!data) {
|
||||
const response = await fetch('/api/config/settings', {
|
||||
method: 'GET',
|
||||
@@ -131,25 +154,39 @@ export const DefaultsSettings: React.FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
const model = typeof data.defaultModel === 'string' && data.defaultModel.trim().length > 0 ? data.defaultModel.trim() : undefined;
|
||||
const variant = typeof data.defaultVariant === 'string' && data.defaultVariant.trim().length > 0 ? data.defaultVariant.trim() : undefined;
|
||||
const agent = typeof data.defaultAgent === 'string' && data.defaultAgent.trim().length > 0 ? data.defaultAgent.trim() : undefined;
|
||||
const zen = typeof data.zenModel === 'string' && data.zenModel.trim().length > 0 ? data.zenModel.trim() : undefined;
|
||||
if (data) {
|
||||
const model =
|
||||
typeof data.defaultModel === 'string' && data.defaultModel.trim().length > 0
|
||||
? data.defaultModel.trim()
|
||||
: undefined;
|
||||
const variant =
|
||||
typeof data.defaultVariant === 'string' && data.defaultVariant.trim().length > 0
|
||||
? data.defaultVariant.trim()
|
||||
: undefined;
|
||||
const agent =
|
||||
typeof data.defaultAgent === 'string' && data.defaultAgent.trim().length > 0
|
||||
? data.defaultAgent.trim()
|
||||
: undefined;
|
||||
const zen =
|
||||
typeof data.zenModel === 'string' && data.zenModel.trim().length > 0
|
||||
? data.zenModel.trim()
|
||||
: undefined;
|
||||
const gitProviderId =
|
||||
typeof data.gitProviderId === 'string' && data.gitProviderId.trim().length > 0
|
||||
? data.gitProviderId.trim()
|
||||
: undefined;
|
||||
const gitModelId =
|
||||
typeof data.gitModelId === 'string' && data.gitModelId.trim().length > 0
|
||||
? data.gitModelId.trim()
|
||||
: undefined;
|
||||
|
||||
if (model !== undefined) {
|
||||
setDefaultModel(model);
|
||||
}
|
||||
if (variant !== undefined) {
|
||||
setDefaultVariant(variant);
|
||||
}
|
||||
if (agent !== undefined) {
|
||||
setDefaultAgent(agent);
|
||||
}
|
||||
if (zen !== undefined) {
|
||||
setSettingsZenModel(zen);
|
||||
}
|
||||
}
|
||||
if (model !== undefined) setDefaultModel(model);
|
||||
if (variant !== undefined) setDefaultVariant(variant);
|
||||
if (agent !== undefined) setDefaultAgent(agent);
|
||||
if (zen !== undefined) setSettingsZenModel(zen);
|
||||
if (gitProviderId !== undefined) setSettingsGitProviderId(gitProviderId);
|
||||
if (gitModelId !== undefined) setSettingsGitModelId(gitModelId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to load defaults settings:', error);
|
||||
} finally {
|
||||
@@ -157,88 +194,78 @@ export const DefaultsSettings: React.FC = () => {
|
||||
}
|
||||
};
|
||||
loadSettings();
|
||||
}, [setSettingsZenModel]);
|
||||
}, [setSettingsGitModelId, setSettingsGitProviderId, setSettingsZenModel]);
|
||||
|
||||
const handleModelChange = React.useCallback(
|
||||
async (providerId: string, modelId: string) => {
|
||||
const newValue = providerId && modelId ? `${providerId}/${modelId}` : undefined;
|
||||
setDefaultModel(newValue);
|
||||
setDefaultVariant(undefined);
|
||||
setSettingsDefaultVariant(undefined);
|
||||
setCurrentVariant(undefined);
|
||||
setSettingsDefaultModel(newValue);
|
||||
|
||||
const handleModelChange = React.useCallback(async (providerId: string, modelId: string) => {
|
||||
const newValue = providerId && modelId ? `${providerId}/${modelId}` : undefined;
|
||||
setDefaultModel(newValue);
|
||||
|
||||
// Reset variant when model changes (model-specific)
|
||||
setDefaultVariant(undefined);
|
||||
setSettingsDefaultVariant(undefined);
|
||||
setCurrentVariant(undefined);
|
||||
|
||||
// Update config store settings default (used by setAgent logic)
|
||||
setSettingsDefaultModel(newValue);
|
||||
|
||||
// Also update current model immediately so new sessions use this model
|
||||
if (providerId && modelId) {
|
||||
const provider = providers.find((p) => p.id === providerId);
|
||||
if (provider) {
|
||||
setProvider(providerId);
|
||||
setModel(modelId);
|
||||
if (providerId && modelId) {
|
||||
const provider = providers.find((p) => p.id === providerId);
|
||||
if (provider) {
|
||||
setProvider(providerId);
|
||||
setModel(modelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await updateDesktopSettings({
|
||||
defaultModel: newValue ?? '',
|
||||
defaultVariant: '',
|
||||
});
|
||||
|
||||
{
|
||||
const response = await fetch('/api/config/settings', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ defaultModel: newValue }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
console.warn('Failed to save default model to server:', response.status, response.statusText);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to save default model:', error);
|
||||
}
|
||||
}, [providers, setCurrentVariant, setProvider, setModel, setSettingsDefaultModel, setSettingsDefaultVariant]);
|
||||
try {
|
||||
await updateDesktopSettings({ defaultModel: newValue ?? '', defaultVariant: '' });
|
||||
const response = await fetch('/api/config/settings', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ defaultModel: newValue }),
|
||||
});
|
||||
if (!response.ok) {
|
||||
console.warn('Failed to save default model to server:', response.status, response.statusText);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to save default model:', error);
|
||||
}
|
||||
},
|
||||
[providers, setCurrentVariant, setModel, setProvider, setSettingsDefaultModel, setSettingsDefaultVariant]
|
||||
);
|
||||
|
||||
const DEFAULT_VARIANT_VALUE = '__default__';
|
||||
|
||||
const handleVariantChange = React.useCallback(async (variant: string) => {
|
||||
const newValue = variant === DEFAULT_VARIANT_VALUE ? undefined : (variant || undefined);
|
||||
setDefaultVariant(newValue);
|
||||
setSettingsDefaultVariant(newValue);
|
||||
setCurrentVariant(newValue);
|
||||
const handleVariantChange = React.useCallback(
|
||||
async (variant: string) => {
|
||||
const newValue = variant === DEFAULT_VARIANT_VALUE ? undefined : variant || undefined;
|
||||
setDefaultVariant(newValue);
|
||||
setSettingsDefaultVariant(newValue);
|
||||
setCurrentVariant(newValue);
|
||||
|
||||
try {
|
||||
await updateDesktopSettings({
|
||||
defaultVariant: newValue ?? '',
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Failed to save default variant:', error);
|
||||
}
|
||||
}, [setCurrentVariant, setSettingsDefaultVariant]);
|
||||
try {
|
||||
await updateDesktopSettings({ defaultVariant: newValue ?? '' });
|
||||
} catch (error) {
|
||||
console.warn('Failed to save default variant:', error);
|
||||
}
|
||||
},
|
||||
[setCurrentVariant, setSettingsDefaultVariant]
|
||||
);
|
||||
|
||||
const handleAgentChange = React.useCallback(async (agentName: string) => {
|
||||
const newValue = agentName || undefined;
|
||||
setDefaultAgent(newValue);
|
||||
const handleAgentChange = React.useCallback(
|
||||
async (agentName: string) => {
|
||||
const newValue = agentName || undefined;
|
||||
setDefaultAgent(newValue);
|
||||
setSettingsDefaultAgent(newValue);
|
||||
|
||||
// Update config store settings default
|
||||
setSettingsDefaultAgent(newValue);
|
||||
if (agentName) {
|
||||
setAgent(agentName);
|
||||
}
|
||||
|
||||
// Update current agent (setAgent will respect settingsDefaultModel)
|
||||
if (agentName) {
|
||||
setAgent(agentName);
|
||||
}
|
||||
|
||||
try {
|
||||
await updateDesktopSettings({
|
||||
defaultAgent: newValue ?? '',
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Failed to save default agent:', error);
|
||||
}
|
||||
}, [setAgent, setSettingsDefaultAgent]);
|
||||
try {
|
||||
await updateDesktopSettings({ defaultAgent: newValue ?? '' });
|
||||
} catch (error) {
|
||||
console.warn('Failed to save default agent:', error);
|
||||
}
|
||||
},
|
||||
[setAgent, setSettingsDefaultAgent]
|
||||
);
|
||||
|
||||
const availableVariants = React.useMemo(() => {
|
||||
if (!parsedModel.providerId || !parsedModel.modelId) return [];
|
||||
@@ -247,9 +274,7 @@ export const DefaultsSettings: React.FC = () => {
|
||||
| { variants?: Record<string, unknown> }
|
||||
| undefined;
|
||||
const variants = model?.variants;
|
||||
if (!variants) {
|
||||
return [];
|
||||
}
|
||||
if (!variants) return [];
|
||||
return Object.keys(variants);
|
||||
}, [parsedModel.modelId, parsedModel.providerId, providers]);
|
||||
|
||||
@@ -266,27 +291,37 @@ export const DefaultsSettings: React.FC = () => {
|
||||
}
|
||||
}, [defaultVariant, setCurrentVariant, setSettingsDefaultVariant, supportsVariants]);
|
||||
|
||||
const handleAutoWorktreeChange = React.useCallback(async (enabled: boolean) => {
|
||||
setSettingsAutoCreateWorktree(enabled);
|
||||
try {
|
||||
await updateDesktopSettings({
|
||||
autoCreateWorktree: enabled,
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Failed to save auto create worktree setting:', error);
|
||||
}
|
||||
}, [setSettingsAutoCreateWorktree]);
|
||||
const handleAutoWorktreeChange = React.useCallback(
|
||||
async (enabled: boolean) => {
|
||||
setSettingsAutoCreateWorktree(enabled);
|
||||
try {
|
||||
await updateDesktopSettings({ autoCreateWorktree: enabled });
|
||||
} catch (error) {
|
||||
console.warn('Failed to save auto create worktree setting:', error);
|
||||
}
|
||||
},
|
||||
[setSettingsAutoCreateWorktree]
|
||||
);
|
||||
|
||||
const handleZenModelChange = React.useCallback(async (modelId: string) => {
|
||||
setSettingsZenModel(modelId);
|
||||
try {
|
||||
await updateDesktopSettings({
|
||||
zenModel: modelId,
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Failed to save zen model setting:', error);
|
||||
}
|
||||
}, [setSettingsZenModel]);
|
||||
const handleUtilityModelChange = React.useCallback(
|
||||
async (providerId: string, modelId: string) => {
|
||||
setSettingsGitProviderId(providerId);
|
||||
setSettingsGitModelId(modelId);
|
||||
if (providerId === UTILITY_PROVIDER_ID) {
|
||||
setSettingsZenModel(modelId);
|
||||
}
|
||||
try {
|
||||
await updateDesktopSettings({
|
||||
gitProviderId: providerId,
|
||||
gitModelId: modelId,
|
||||
...(providerId === UTILITY_PROVIDER_ID ? { zenModel: modelId } : {}),
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('Failed to save utility model setting:', error);
|
||||
}
|
||||
},
|
||||
[setSettingsGitModelId, setSettingsGitProviderId, setSettingsZenModel]
|
||||
);
|
||||
|
||||
if (isLoading) {
|
||||
return null;
|
||||
@@ -319,85 +354,65 @@ export const DefaultsSettings: React.FC = () => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className={cn("flex flex-col gap-2 py-1 sm:flex-row sm:items-center sm:gap-8")}>
|
||||
<div className={cn('flex flex-col gap-2 py-1 sm:flex-row sm:items-center sm:gap-8')}>
|
||||
<div className="flex min-w-0 flex-col sm:w-56 shrink-0">
|
||||
<span className="typography-ui-label text-foreground">Default Model</span>
|
||||
</div>
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2 sm:w-fit sm:flex-initial">
|
||||
<ModelSelector
|
||||
providerId={parsedModel.providerId}
|
||||
modelId={parsedModel.modelId}
|
||||
onChange={handleModelChange}
|
||||
/>
|
||||
<ModelSelector providerId={parsedModel.providerId} modelId={parsedModel.modelId} onChange={handleModelChange} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 py-1 sm:flex-row sm:items-center sm:gap-8">
|
||||
<div className="flex min-w-0 flex-col sm:w-56 shrink-0">
|
||||
<span className="typography-ui-label text-foreground">Default Thinking</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 sm:w-fit">
|
||||
<Select value={defaultVariant ?? DEFAULT_VARIANT_VALUE} onValueChange={handleVariantChange} disabled={!supportsVariants}>
|
||||
<SelectTrigger className="w-fit min-w-[120px]">
|
||||
<SelectValue placeholder="Thinking" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={DEFAULT_VARIANT_VALUE}>Default</SelectItem>
|
||||
{availableVariants.map((variant) => (
|
||||
<SelectItem key={variant} value={variant}>
|
||||
{variant}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 py-1 sm:flex-row sm:items-center sm:gap-8">
|
||||
<div className="flex min-w-0 flex-col sm:w-56 shrink-0">
|
||||
<span className="typography-ui-label text-foreground">Default Thinking</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 sm:w-fit">
|
||||
<Select value={defaultVariant ?? DEFAULT_VARIANT_VALUE} onValueChange={handleVariantChange} disabled={!supportsVariants}>
|
||||
<SelectTrigger className="w-fit min-w-[120px]">
|
||||
<SelectValue placeholder="Thinking" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value={DEFAULT_VARIANT_VALUE}>Default</SelectItem>
|
||||
{availableVariants.map((variant) => (
|
||||
<SelectItem key={variant} value={variant}>
|
||||
{variant}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 py-1 sm:flex-row sm:items-center sm:gap-8">
|
||||
<div className="flex min-w-0 flex-col sm:w-56 shrink-0">
|
||||
<span className="typography-ui-label text-foreground">Default Agent</span>
|
||||
</div>
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2 sm:w-fit sm:flex-initial">
|
||||
<AgentSelector
|
||||
agentName={defaultAgent || ''}
|
||||
onChange={handleAgentChange}
|
||||
/>
|
||||
<AgentSelector agentName={defaultAgent || ''} onChange={handleAgentChange} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 py-1 sm:flex-row sm:items-center sm:gap-8">
|
||||
<div className="flex min-w-0 flex-col sm:w-56 shrink-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="typography-ui-label text-foreground">Zen Model</span>
|
||||
<span className="typography-ui-label text-foreground">Utility Model</span>
|
||||
<Tooltip delayDuration={1000}>
|
||||
<TooltipTrigger asChild>
|
||||
<RiInformationLine className="h-3.5 w-3.5 text-muted-foreground/60 cursor-help" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent sideOffset={8} className="max-w-xs">
|
||||
The free model used for lightweight internal tasks like commit message generation, PR descriptions, notification summarization, and TTS text summarization.
|
||||
The model used for lightweight background tasks like commit messages, PR descriptions, and summarization.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 sm:w-fit">
|
||||
{zenModelsLoading ? (
|
||||
<span className="typography-meta text-muted-foreground">Loading models...</span>
|
||||
) : zenModels.length > 0 ? (
|
||||
<Select value={selectedZenModel} onValueChange={handleZenModelChange}>
|
||||
<SelectTrigger className="w-fit min-w-[120px]">
|
||||
<SelectValue placeholder="Select model" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{zenModels.map((model) => (
|
||||
<SelectItem key={model.id} value={model.id}>
|
||||
{model.id}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
) : (
|
||||
<span className="typography-meta text-muted-foreground">No free models available</span>
|
||||
)}
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2 sm:w-fit sm:flex-initial">
|
||||
<ModelSelector
|
||||
providerId={utilityDisplayModel.providerId}
|
||||
modelId={utilityDisplayModel.modelId}
|
||||
onChange={handleUtilityModelChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -414,11 +429,7 @@ export const DefaultsSettings: React.FC = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
checked={showDeletionDialog}
|
||||
onChange={setShowDeletionDialog}
|
||||
ariaLabel="Show deletion dialog"
|
||||
/>
|
||||
<Checkbox checked={showDeletionDialog} onChange={setShowDeletionDialog} ariaLabel="Show deletion dialog" />
|
||||
<span className="typography-ui-label text-foreground">Show Deletion Dialog</span>
|
||||
</div>
|
||||
|
||||
@@ -462,9 +473,7 @@ export const DefaultsSettings: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user