Refactor UUID generation, remove unused logger and encryption utilities, and clean up request handling
- Updated `generateUUID` function for improved readability and performance. - Deleted `logger.ts`, `other.ts`, `request.ts`, `storage.ts`, `tansParams.ts`, and `validate.ts` as they were no longer needed. - Simplified TypeScript configuration by removing unnecessary paths and aliases. - Enhanced Vite configuration for better project structure and maintainability.
This commit is contained in:
355
runtime-shared/lib/providers.ts
Normal file
355
runtime-shared/lib/providers.ts
Normal file
@@ -0,0 +1,355 @@
|
||||
export const PROVIDER_TYPES = [
|
||||
'anthropic',
|
||||
'openai',
|
||||
'google',
|
||||
'openrouter',
|
||||
'ark',
|
||||
'moonshot',
|
||||
'siliconflow',
|
||||
'deepseek',
|
||||
'minimax-portal',
|
||||
'minimax-portal-cn',
|
||||
'modelstudio',
|
||||
'ollama',
|
||||
'custom',
|
||||
] as const;
|
||||
|
||||
export type ProviderType = (typeof PROVIDER_TYPES)[number];
|
||||
|
||||
export const BUILTIN_PROVIDER_TYPES = [
|
||||
'anthropic',
|
||||
'openai',
|
||||
'google',
|
||||
'openrouter',
|
||||
'ark',
|
||||
'moonshot',
|
||||
'siliconflow',
|
||||
'deepseek',
|
||||
'minimax-portal',
|
||||
'minimax-portal-cn',
|
||||
'modelstudio',
|
||||
'ollama',
|
||||
] as const;
|
||||
|
||||
export const OLLAMA_PLACEHOLDER_API_KEY = 'ollama-local';
|
||||
|
||||
export interface ProviderConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
type: ProviderType;
|
||||
baseUrl?: string;
|
||||
apiProtocol?: 'openai-completions' | 'openai-responses' | 'anthropic-messages';
|
||||
headers?: Record<string, string>;
|
||||
model?: string;
|
||||
fallbackModels?: string[];
|
||||
fallbackProviderIds?: string[];
|
||||
enabled: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ProviderWithKeyInfo extends ProviderConfig {
|
||||
hasKey: boolean;
|
||||
keyMasked: string | null;
|
||||
}
|
||||
|
||||
export interface ProviderTypeInfo {
|
||||
id: ProviderType;
|
||||
name: string;
|
||||
icon: string;
|
||||
placeholder: string;
|
||||
model?: string;
|
||||
requiresApiKey: boolean;
|
||||
defaultBaseUrl?: string;
|
||||
showBaseUrl?: boolean;
|
||||
showModelId?: boolean;
|
||||
showModelIdInDevModeOnly?: boolean;
|
||||
modelIdPlaceholder?: string;
|
||||
defaultModelId?: string;
|
||||
isOAuth?: boolean;
|
||||
supportsApiKey?: boolean;
|
||||
apiKeyUrl?: string;
|
||||
docsUrl?: string;
|
||||
docsUrlZh?: string;
|
||||
codePlanPresetBaseUrl?: string;
|
||||
codePlanPresetModelId?: string;
|
||||
codePlanDocsUrl?: string;
|
||||
hidden?: boolean;
|
||||
}
|
||||
|
||||
export type ProviderAuthMode =
|
||||
| 'api_key'
|
||||
| 'oauth_device'
|
||||
| 'oauth_browser'
|
||||
| 'local';
|
||||
|
||||
export type ProviderVendorCategory =
|
||||
| 'official'
|
||||
| 'compatible'
|
||||
| 'local'
|
||||
| 'custom';
|
||||
|
||||
export interface ProviderVendorInfo extends ProviderTypeInfo {
|
||||
category: ProviderVendorCategory;
|
||||
envVar?: string;
|
||||
supportedAuthModes: ProviderAuthMode[];
|
||||
defaultAuthMode: ProviderAuthMode;
|
||||
supportsMultipleAccounts: boolean;
|
||||
}
|
||||
|
||||
export interface ProviderAccount {
|
||||
id: string;
|
||||
vendorId: ProviderType;
|
||||
label: string;
|
||||
authMode: ProviderAuthMode;
|
||||
baseUrl?: string;
|
||||
apiProtocol?: 'openai-completions' | 'openai-responses' | 'anthropic-messages';
|
||||
headers?: Record<string, string>;
|
||||
model?: string;
|
||||
fallbackModels?: string[];
|
||||
fallbackAccountIds?: string[];
|
||||
enabled: boolean;
|
||||
isDefault: boolean;
|
||||
metadata?: {
|
||||
region?: string;
|
||||
email?: string;
|
||||
resourceUrl?: string;
|
||||
customModels?: string[];
|
||||
};
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export const PROVIDER_TYPE_INFO: ProviderTypeInfo[] = [
|
||||
{
|
||||
id: 'anthropic',
|
||||
name: 'Anthropic',
|
||||
icon: 'A',
|
||||
placeholder: 'sk-ant-api03-...',
|
||||
model: 'Claude',
|
||||
requiresApiKey: true,
|
||||
docsUrl: 'https://platform.claude.com/docs/en/api/overview',
|
||||
},
|
||||
{
|
||||
id: 'openai',
|
||||
name: 'OpenAI',
|
||||
icon: 'O',
|
||||
placeholder: 'sk-proj-...',
|
||||
model: 'GPT',
|
||||
requiresApiKey: true,
|
||||
isOAuth: true,
|
||||
supportsApiKey: true,
|
||||
defaultModelId: 'gpt-5.4',
|
||||
showModelId: true,
|
||||
showModelIdInDevModeOnly: true,
|
||||
modelIdPlaceholder: 'gpt-5.4',
|
||||
apiKeyUrl: 'https://platform.openai.com/api-keys',
|
||||
},
|
||||
{
|
||||
id: 'google',
|
||||
name: 'Google',
|
||||
icon: 'G',
|
||||
placeholder: 'AIza...',
|
||||
model: 'Gemini',
|
||||
requiresApiKey: true,
|
||||
isOAuth: true,
|
||||
supportsApiKey: true,
|
||||
defaultModelId: 'gemini-3-pro-preview',
|
||||
showModelId: true,
|
||||
showModelIdInDevModeOnly: true,
|
||||
modelIdPlaceholder: 'gemini-3-pro-preview',
|
||||
apiKeyUrl: 'https://aistudio.google.com/app/apikey',
|
||||
},
|
||||
{
|
||||
id: 'openrouter',
|
||||
name: 'OpenRouter',
|
||||
icon: 'R',
|
||||
placeholder: 'sk-or-v1-...',
|
||||
model: 'Multi-Model',
|
||||
requiresApiKey: true,
|
||||
showModelId: true,
|
||||
modelIdPlaceholder: 'openai/gpt-5.4',
|
||||
defaultModelId: 'openai/gpt-5.4',
|
||||
docsUrl: 'https://openrouter.ai/models',
|
||||
},
|
||||
{
|
||||
id: 'minimax-portal-cn',
|
||||
name: 'MiniMax (CN)',
|
||||
icon: 'M',
|
||||
placeholder: 'sk-...',
|
||||
model: 'MiniMax',
|
||||
requiresApiKey: false,
|
||||
isOAuth: true,
|
||||
supportsApiKey: true,
|
||||
defaultModelId: 'MiniMax-M2.7',
|
||||
showModelId: true,
|
||||
showModelIdInDevModeOnly: true,
|
||||
modelIdPlaceholder: 'MiniMax-M2.7',
|
||||
apiKeyUrl: 'https://platform.minimaxi.com/',
|
||||
},
|
||||
{
|
||||
id: 'moonshot',
|
||||
name: 'Moonshot (CN)',
|
||||
icon: 'K',
|
||||
placeholder: 'sk-...',
|
||||
model: 'Kimi',
|
||||
requiresApiKey: true,
|
||||
defaultBaseUrl: 'https://api.moonshot.cn/v1',
|
||||
defaultModelId: 'kimi-k2.5',
|
||||
docsUrl: 'https://platform.moonshot.cn/',
|
||||
},
|
||||
{
|
||||
id: 'siliconflow',
|
||||
name: 'SiliconFlow (CN)',
|
||||
icon: 'S',
|
||||
placeholder: 'sk-...',
|
||||
model: 'Multi-Model',
|
||||
requiresApiKey: true,
|
||||
defaultBaseUrl: 'https://api.siliconflow.cn/v1',
|
||||
showModelId: true,
|
||||
showModelIdInDevModeOnly: true,
|
||||
modelIdPlaceholder: 'deepseek-ai/DeepSeek-V3',
|
||||
defaultModelId: 'deepseek-ai/DeepSeek-V3',
|
||||
docsUrl: 'https://docs.siliconflow.cn/cn/userguide/introduction',
|
||||
},
|
||||
{
|
||||
id: 'deepseek',
|
||||
name: 'DeepSeek',
|
||||
icon: 'D',
|
||||
placeholder: 'sk-...',
|
||||
model: 'DeepSeek',
|
||||
requiresApiKey: true,
|
||||
defaultBaseUrl: 'https://api.deepseek.com/v1',
|
||||
showModelId: true,
|
||||
modelIdPlaceholder: 'deepseek-chat',
|
||||
defaultModelId: 'deepseek-chat',
|
||||
apiKeyUrl: 'https://platform.deepseek.com/api_keys',
|
||||
docsUrl: 'https://api-docs.deepseek.com/',
|
||||
},
|
||||
{
|
||||
id: 'minimax-portal',
|
||||
name: 'MiniMax (Global)',
|
||||
icon: 'M',
|
||||
placeholder: 'sk-...',
|
||||
model: 'MiniMax',
|
||||
requiresApiKey: false,
|
||||
isOAuth: true,
|
||||
supportsApiKey: true,
|
||||
defaultModelId: 'MiniMax-M2.7',
|
||||
showModelId: true,
|
||||
showModelIdInDevModeOnly: true,
|
||||
modelIdPlaceholder: 'MiniMax-M2.7',
|
||||
apiKeyUrl: 'https://platform.minimax.io',
|
||||
},
|
||||
{
|
||||
id: 'modelstudio',
|
||||
name: 'Model Studio',
|
||||
icon: 'Q',
|
||||
placeholder: 'sk-...',
|
||||
model: 'Qwen',
|
||||
requiresApiKey: true,
|
||||
defaultBaseUrl: 'https://coding.dashscope.aliyuncs.com/v1',
|
||||
showBaseUrl: true,
|
||||
defaultModelId: 'qwen3.5-plus',
|
||||
showModelId: true,
|
||||
showModelIdInDevModeOnly: true,
|
||||
modelIdPlaceholder: 'qwen3.5-plus',
|
||||
apiKeyUrl: 'https://bailian.console.aliyun.com/',
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
id: 'ark',
|
||||
name: 'ByteDance Ark',
|
||||
icon: 'B',
|
||||
placeholder: 'your-ark-api-key',
|
||||
model: 'Doubao',
|
||||
requiresApiKey: true,
|
||||
defaultBaseUrl: 'https://ark.cn-beijing.volces.com/api/v3',
|
||||
showBaseUrl: true,
|
||||
showModelId: true,
|
||||
modelIdPlaceholder: 'ep-20260228000000-xxxxx',
|
||||
docsUrl: 'https://www.volcengine.com/',
|
||||
codePlanPresetBaseUrl: 'https://ark.cn-beijing.volces.com/api/coding/v3',
|
||||
codePlanPresetModelId: 'ark-code-latest',
|
||||
codePlanDocsUrl: 'https://www.volcengine.com/docs/82379/1928261?lang=zh',
|
||||
},
|
||||
{
|
||||
id: 'ollama',
|
||||
name: 'Ollama',
|
||||
icon: 'L',
|
||||
placeholder: 'Not required',
|
||||
requiresApiKey: false,
|
||||
defaultBaseUrl: 'http://localhost:11434/v1',
|
||||
showBaseUrl: true,
|
||||
showModelId: true,
|
||||
modelIdPlaceholder: 'qwen3:latest',
|
||||
},
|
||||
{
|
||||
id: 'custom',
|
||||
name: 'Custom',
|
||||
icon: 'C',
|
||||
placeholder: 'API key...',
|
||||
requiresApiKey: true,
|
||||
showBaseUrl: true,
|
||||
showModelId: true,
|
||||
modelIdPlaceholder: 'your-provider/model-id',
|
||||
docsUrl: 'https://icnnp7d0dymg.feishu.cn/wiki/BmiLwGBcEiloZDkdYnGc8RWnn6d#Ee1ldfvKJoVGvfxc32mcILwenth',
|
||||
docsUrlZh: 'https://icnnp7d0dymg.feishu.cn/wiki/BmiLwGBcEiloZDkdYnGc8RWnn6d#IWQCdfe5fobGU3xf3UGcgbLynGh',
|
||||
},
|
||||
];
|
||||
|
||||
export function getProviderIconUrl(_type: ProviderType | string): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function shouldInvertInDark(_type: ProviderType | string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
export const SETUP_PROVIDERS = PROVIDER_TYPE_INFO;
|
||||
|
||||
export function getProviderTypeInfo(type: ProviderType): ProviderTypeInfo | undefined {
|
||||
return PROVIDER_TYPE_INFO.find((providerType) => providerType.id === type);
|
||||
}
|
||||
|
||||
export function getProviderDocsUrl(
|
||||
provider: Pick<ProviderTypeInfo, 'docsUrl' | 'docsUrlZh'> | undefined,
|
||||
language: string,
|
||||
): string | undefined {
|
||||
if (!provider?.docsUrl) {
|
||||
return undefined;
|
||||
}
|
||||
if (language.startsWith('zh') && provider.docsUrlZh) {
|
||||
return provider.docsUrlZh;
|
||||
}
|
||||
return provider.docsUrl;
|
||||
}
|
||||
|
||||
export function shouldShowProviderModelId(
|
||||
provider: Pick<ProviderTypeInfo, 'showModelId' | 'showModelIdInDevModeOnly'> | undefined,
|
||||
devModeUnlocked: boolean,
|
||||
): boolean {
|
||||
if (!provider?.showModelId) return false;
|
||||
if (provider.showModelIdInDevModeOnly && !devModeUnlocked) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function resolveProviderModelForSave(
|
||||
provider: Pick<ProviderTypeInfo, 'defaultModelId' | 'showModelId' | 'showModelIdInDevModeOnly'> | undefined,
|
||||
modelId: string,
|
||||
devModeUnlocked: boolean,
|
||||
): string | undefined {
|
||||
if (!shouldShowProviderModelId(provider, devModeUnlocked)) {
|
||||
return undefined;
|
||||
}
|
||||
const trimmedModelId = modelId.trim();
|
||||
return trimmedModelId || provider?.defaultModelId || undefined;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user