perf: memo GridCard, fuse save fns, fix slash tab active color
This commit is contained in:
@@ -7,7 +7,7 @@ const PROVIDER_URLS: Record<string, string> = {
|
||||
openrouter: 'https://openrouter.ai/api/v1',
|
||||
mistral: 'https://api.mistral.ai/v1',
|
||||
zai: 'https://api.zukijourney.com/v1',
|
||||
minimax: 'https://api.minimax.chat/v1',
|
||||
minimax: 'https://api.minimax.io/v1',
|
||||
glm: 'https://open.bigmodel.ai/api/paas/v4',
|
||||
};
|
||||
|
||||
@@ -17,13 +17,21 @@ export const PROVIDER_MODEL_SUGGESTIONS: Record<string, string[]> = {
|
||||
anthropic: ['claude-3-5-sonnet-latest', 'claude-3-5-haiku-latest', 'claude-3-opus-latest'],
|
||||
google: ['gemini-1.5-flash', 'gemini-1.5-pro', 'gemini-2.0-flash-exp'],
|
||||
deepseek: ['deepseek-chat', 'deepseek-coder'],
|
||||
minimax: ['abab6.5-chat', 'abab6.5s-chat'],
|
||||
minimax: ['MiniMax-M2.7', 'MiniMax-M2.5', 'MiniMax-M2-her'],
|
||||
mistral: ['mistral-small-latest', 'mistral-medium-latest', 'mistral-large-latest'],
|
||||
glm: ['glm-4', 'glm-4-flash'],
|
||||
openrouter: ['openai/gpt-4o-mini', 'anthropic/claude-3.5-sonnet', 'deepseek/deepseek-chat'],
|
||||
custom: [],
|
||||
};
|
||||
|
||||
/**
|
||||
* Result of fetching models - includes whether they came from the real API or fallbacks
|
||||
*/
|
||||
export interface FetchModelsResult {
|
||||
models: string[]
|
||||
fromApi: boolean // true = fetched from provider API, false = fallback suggestions
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically queries the provider's /models endpoint using the user's API Key
|
||||
* to fetch their actual available models list instead of relying on hardcoded choices.
|
||||
@@ -32,21 +40,32 @@ export async function fetchLiveModelsForProvider(
|
||||
provider: AiGatewayProvider,
|
||||
apiKey: string,
|
||||
customBaseUrl?: string
|
||||
): Promise<string[]> {
|
||||
): Promise<FetchModelsResult> {
|
||||
try {
|
||||
// Anthropic and Google do not expose a public list via a simple key GET /models (or need specific formats)
|
||||
// We fall back to the popular defaults for those.
|
||||
if (provider === 'anthropic' || provider === 'anthropic_custom' || provider === 'google') {
|
||||
const standardProvider = provider === 'anthropic_custom' ? 'anthropic' : provider;
|
||||
return PROVIDER_MODEL_SUGGESTIONS[standardProvider] ?? [];
|
||||
if (
|
||||
provider === 'anthropic' ||
|
||||
provider === 'anthropic_custom' ||
|
||||
provider === 'custom_anthropic' ||
|
||||
provider === 'google' ||
|
||||
provider === 'minimax'
|
||||
) {
|
||||
const standardProvider =
|
||||
provider === 'anthropic_custom' || provider === 'custom_anthropic'
|
||||
? 'anthropic'
|
||||
: provider;
|
||||
const models = PROVIDER_MODEL_SUGGESTIONS[standardProvider] ?? [];
|
||||
return { models, fromApi: false };
|
||||
}
|
||||
|
||||
const baseUrl = provider === 'custom'
|
||||
const baseUrl = (provider === 'custom' || provider === 'custom_openai')
|
||||
? customBaseUrl?.replace(/\/$/, '')
|
||||
: PROVIDER_URLS[provider];
|
||||
|
||||
if (!baseUrl) {
|
||||
return PROVIDER_MODEL_SUGGESTIONS[provider] ?? [];
|
||||
const models = PROVIDER_MODEL_SUGGESTIONS[provider] ?? [];
|
||||
return { models, fromApi: false };
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
|
||||
@@ -63,7 +82,9 @@ export async function fetchLiveModelsForProvider(
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
return PROVIDER_MODEL_SUGGESTIONS[provider] ?? [];
|
||||
console.warn(`[fetchLiveModelsForProvider] API returned ${response.status} for ${provider}`);
|
||||
const models = PROVIDER_MODEL_SUGGESTIONS[provider] ?? [];
|
||||
return { models, fromApi: false };
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
@@ -73,11 +94,24 @@ export async function fetchLiveModelsForProvider(
|
||||
.sort();
|
||||
|
||||
if (fetched.length > 0) {
|
||||
return fetched;
|
||||
console.log(`[fetchLiveModelsForProvider] Got ${fetched.length} models from ${provider} API:`, fetched);
|
||||
return { models: fetched, fromApi: true };
|
||||
} else {
|
||||
console.warn(`[fetchLiveModelsForProvider] API returned empty data array for ${provider}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`[fetchLiveModelsForProvider] Failed to fetch live models for ${provider}, using fallbacks:`, err);
|
||||
console.warn(`[fetchLiveModelsForProvider] Failed to fetch live models for ${provider}:`, err);
|
||||
}
|
||||
|
||||
return PROVIDER_MODEL_SUGGESTIONS[provider] ?? [];
|
||||
const fallbackProvider =
|
||||
provider === 'custom_openai'
|
||||
? 'openai'
|
||||
: provider === 'custom_anthropic'
|
||||
? 'anthropic'
|
||||
: provider === 'anthropic_custom'
|
||||
? 'anthropic'
|
||||
: provider;
|
||||
|
||||
const models = PROVIDER_MODEL_SUGGESTIONS[fallbackProvider] ?? [];
|
||||
return { models, fromApi: false };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user