fix(provider): ollama provider fix (#246)

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Haze <hazeone@users.noreply.github.com>
This commit is contained in:
Haze
2026-03-01 17:40:07 +08:00
committed by GitHub
Unverified
parent a8f61d5a61
commit 7d0621dcc2
4 changed files with 48 additions and 5 deletions

View File

@@ -29,6 +29,7 @@ import {
PROVIDER_TYPE_INFO,
type ProviderType,
getProviderIconUrl,
resolveProviderApiKeyForSave,
shouldInvertInDark,
} from '@/lib/providers';
import { cn } from '@/lib/utils';
@@ -66,6 +67,7 @@ export function ProvidersSettings() {
// Only custom supports multiple instances.
// Built-in providers remain singleton by type.
const id = type === 'custom' ? `custom-${crypto.randomUUID()}` : type;
const effectiveApiKey = resolveProviderApiKeyForSave(type, apiKey);
try {
await addProvider(
{
@@ -76,7 +78,7 @@ export function ProvidersSettings() {
model: options?.model,
enabled: true,
},
apiKey.trim() || undefined
effectiveApiKey
);
// Auto-set as default if no default is currently configured
@@ -261,6 +263,12 @@ function ProviderCard({
}
}
// Keep Ollama key optional in UI, but persist a placeholder when
// editing legacy configs that have no stored key.
if (provider.type === 'ollama' && !provider.hasKey && !payload.newApiKey) {
payload.newApiKey = resolveProviderApiKeyForSave(provider.type, '') as string;
}
if (!payload.newApiKey && !payload.updates) {
onCancelEdit();
setSaving(false);

View File

@@ -21,6 +21,8 @@ export const PROVIDER_TYPES = [
] as const;
export type ProviderType = (typeof PROVIDER_TYPES)[number];
export const OLLAMA_PLACEHOLDER_API_KEY = 'ollama-local';
export interface ProviderConfig {
id: string;
name: string;
@@ -77,7 +79,7 @@ export const PROVIDER_TYPE_INFO: ProviderTypeInfo[] = [
{ id: 'minimax-portal', name: 'MiniMax (Global)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.5', apiKeyUrl: 'https://intl.minimaxi.com/' },
{ id: 'minimax-portal-cn', name: 'MiniMax (CN)', icon: '☁️', placeholder: 'sk-...', model: 'MiniMax', requiresApiKey: false, isOAuth: true, supportsApiKey: true, defaultModelId: 'MiniMax-M2.5', apiKeyUrl: 'https://platform.minimaxi.com/' },
{ id: 'qwen-portal', name: 'Qwen', icon: '☁️', placeholder: 'sk-...', model: 'Qwen', requiresApiKey: false, isOAuth: true, defaultModelId: 'coder-model' },
{ id: 'ollama', name: 'Ollama', icon: '🦙', placeholder: 'Not required', requiresApiKey: false, defaultBaseUrl: 'http://localhost:11434', showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'qwen3:latest' },
{ id: 'ollama', name: 'Ollama', icon: '🦙', placeholder: 'Not required', requiresApiKey: false, defaultBaseUrl: 'http://localhost:11434/v1', showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'qwen3:latest' },
{ id: 'custom', name: 'Custom', icon: '⚙️', placeholder: 'API key...', requiresApiKey: true, showBaseUrl: true, showModelId: true, modelIdPlaceholder: 'your-provider/model-id' },
];
@@ -98,3 +100,12 @@ export const SETUP_PROVIDERS = PROVIDER_TYPE_INFO;
export function getProviderTypeInfo(type: ProviderType): ProviderTypeInfo | undefined {
return PROVIDER_TYPE_INFO.find((t) => t.id === type);
}
/** Normalize provider API key before saving; Ollama uses a local placeholder when blank. */
export function resolveProviderApiKeyForSave(type: ProviderType | string, apiKey: string): string | undefined {
const trimmed = apiKey.trim();
if (type === 'ollama') {
return trimmed || OLLAMA_PLACEHOLDER_API_KEY;
}
return trimmed || undefined;
}

View File

@@ -103,7 +103,7 @@ const defaultSkills: DefaultSkill[] = [
{ id: 'terminal', name: 'Terminal', description: 'Shell command execution' },
];
import { SETUP_PROVIDERS, type ProviderTypeInfo, getProviderIconUrl, shouldInvertInDark } from '@/lib/providers';
import { SETUP_PROVIDERS, type ProviderTypeInfo, getProviderIconUrl, resolveProviderApiKeyForSave, shouldInvertInDark } from '@/lib/providers';
import clawxIcon from '@/assets/logo.svg';
// Use the shared provider registry for setup providers
@@ -970,6 +970,8 @@ function ProviderContent({
: `custom-${crypto.randomUUID()}`)
: selectedProvider;
const effectiveApiKey = resolveProviderApiKeyForSave(selectedProvider, apiKey);
// Save provider config + API key, then set as default
const saveResult = await window.electron.ipcRenderer.invoke(
'provider:save',
@@ -983,7 +985,7 @@ function ProviderContent({
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
},
apiKey || undefined
effectiveApiKey
) as { success: boolean; error?: string };
if (!saveResult.success) {