{"repo": "006784/blog", "files": {"src/lib/ciyuan-providers.ts": {"df079e347e49ad7e9627945216f57ec4a9d944bd": {"t": 1786067751.1784844, "n": 9642, "h": "9ce7b71b218ef445", "c": "export type CiyuanProtocol = 'openai' | 'anthropic' | 'gemini' | 'minimax';\nexport type CiyuanAuthMode = 'bearer' | 'header' | 'query' | 'none';\nexport type CiyuanModelPlacement = 'body' | 'url' | 'both';\n\nexport interface CiyuanModelOption {\n id: string;\n label: string;\n}\n\nexport interface CiyuanProviderConfig {\n id: string;\n label: string;\n color: string;\n protocol: CiyuanProtocol;\n baseUrl: string;\n endpointPath?: string;\n authMode: CiyuanAuthMode;\n authKeyName?: string;\n modelPlacement?: CiyuanModelPlacement;\n models: CiyuanModelOption[];\n extraHeaders?: Record;\n builtin?: boolean;\n keyPlaceholder?: string;\n}\n\nconst OPENAI_PATH = '/chat/completions';\nconst ANTHROPIC_PATH = '/messages';\nconst GEMINI_PATH = '/models/{model}:streamGenerateContent';\nconst MINIMAX_PATH = '/text/chatcompletion_v2';\n\nexport const BUILTIN_CIYUAN_PROVIDERS: CiyuanProviderConfig[] = [\n {\n id: 'openai',\n label: 'OpenAI',\n color: '#10a37f',\n protocol: 'openai',\n baseUrl: 'https://api.openai.com/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'sk-...',\n models: [\n { id: 'gpt-4.1', label: 'gpt-4.1' },\n { id: 'gpt-4.1-mini', label: 'gpt-4.1-mini' },\n { id: 'gpt-4o', label: 'gpt-4o' },\n { id: 'gpt-4o-mini', label: 'gpt-4o-mini' },\n { id: 'o4-mini', label: 'o4-mini' },\n ],\n },\n {\n id: 'anthropic',\n label: 'Anthropic Claude',\n color: '#d4a96a',\n protocol: 'anthropic',\n baseUrl: 'https://api.anthropic.com/v1',\n endpointPath: ANTHROPIC_PATH,\n authMode: 'header',\n authKeyName: 'x-api-key',\n builtin: true,\n keyPlaceholder: 'sk-ant-...',\n models: [\n { id: 'claude-3-7-sonnet-latest', label: 'claude-3-7-sonnet-latest' },\n { id: 'claude-3-5-sonnet-latest', label: 'claude-3-5-sonnet-latest' },\n { id: 'claude-3-5-haiku-latest', label: 'claude-3-5-haiku-latest' },\n ],\n },\n {\n id: 'google',\n label: 'Google Gemini',\n color: '#4285f4',\n protocol: 'gemini',\n baseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n endpointPath: GEMINI_PATH,\n authMode: 'query',\n authKeyName: 'key',\n modelPlacement: 'url',\n builtin: true,\n keyPlaceholder: 'AIza...',\n models: [\n { id: 'gemini-2.0-flash', label: 'gemini-2.0-flash' },\n { id: 'gemini-2.0-flash-lite', label: 'gemini-2.0-flash-lite' },\n { id: 'gemini-1.5-pro', label: 'gemini-1.5-pro' },\n ],\n },\n {\n id: 'deepseek',\n label: 'DeepSeek',\n color: '#536dfe',\n protocol: 'openai',\n baseUrl: 'https://api.deepseek.com/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'sk-...',\n models: [\n { id: 'deepseek-chat', label: 'deepseek-chat' },\n { id: 'deepseek-reasoner', label: 'deepseek-reasoner' },\n ],\n },\n {\n id: 'openrouter',\n label: 'OpenRouter',\n color: '#6e40c9',\n protocol: 'openai',\n baseUrl: 'https://openrouter.ai/api/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'sk-or-...',\n extraHeaders: {\n 'HTTP-Referer': 'https://www.artchain.icu',\n 'X-Title': '词元 AI',\n },\n models: [\n { id: 'openai/gpt-4o-mini', label: 'openai/gpt-4o-mini' },\n { id: 'anthropic/claude-3.5-sonnet', label: 'anthropic/claude-3.5-sonnet' },\n { id: 'google/gemma-3-27b-it:free', label: 'google/gemma-3-27b-it:free' },\n { id: 'meta-llama/llama-3.3-70b-instruct:free', label: 'meta-llama/llama-3.3-70b-instruct:free' },\n ],\n },\n {\n id: 'groq',\n label: 'Groq',\n color: '#f55036',\n protocol: 'openai',\n baseUrl: 'https://api.groq.com/openai/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'gsk_...',\n models: [\n { id: 'llama-3.3-70b-versatile', label: 'llama-3.3-70b-versatile' },\n { id: 'llama-3.1-8b-instant', label: 'llama-3.1-8b-instant' },\n { id: 'mixtral-8x7b-32768', label: 'mixtral-8x7b-32768' },\n ],\n },\n {\n id: 'xai',\n label: 'xAI Grok',\n color: '#111111',\n protocol: 'openai',\n baseUrl: 'https://api.x.ai/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'xai-...',\n models: [\n { id: 'grok-2-latest', label: 'grok-2-latest' },\n { id: 'grok-2-vision-latest', label: 'grok-2-vision-latest' },\n ],\n },\n {\n id: 'moonshot',\n label: 'Moonshot Kimi',\n color: '#3d7eff',\n protocol: 'openai',\n baseUrl: 'https://api.moonshot.cn/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'sk-...',\n models: [\n { id: 'moonshot-v1-8k', label: 'moonshot-v1-8k' },\n { id: 'moonshot-v1-32k', label: 'moonshot-v1-32k' },\n { id: 'moonshot-v1-128k', label: 'moonshot-v1-128k' },\n ],\n },\n {\n id: 'qwen',\n label: 'Qwen / DashScope',\n color: '#7a4cff',\n protocol: 'openai',\n baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'sk-...',\n models: [\n { id: 'qwen-plus', label: 'qwen-plus' },\n { id: 'qwen-max', label: 'qwen-max' },\n { id: 'qwen-turbo', label: 'qwen-turbo' },\n ],\n },\n {\n id: 'siliconflow',\n label: 'SiliconFlow',\n color: '#00a6a6',\n protocol: 'openai',\n baseUrl: 'https://api.siliconflow.cn/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: 'sk-...',\n models: [\n { id: 'Qwen/Qwen2.5-72B-Instruct', label: 'Qwen/Qwen2.5-72B-Instruct' },\n { id: 'deepseek-ai/DeepSeek-V3', label: 'deepseek-ai/DeepSeek-V3' },\n { id: 'deepseek-ai/DeepSeek-R1', label: 'deepseek-ai/DeepSeek-R1' },\n ],\n },\n {\n id: 'mistral',\n label: 'Mistral',\n color: '#ff9a3c',\n protocol: 'openai',\n baseUrl: 'https://api.mistral.ai/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: '...',\n models: [\n { id: 'mistral-large-latest', label: 'mistral-large-latest' },\n { id: 'ministral-8b-latest', label: 'ministral-8b-latest' },\n { id: 'open-mixtral-8x22b', label: 'open-mixtral-8x22b' },\n ],\n },\n {\n id: 'together',\n label: 'Together AI',\n color: '#ff5e5b',\n protocol: 'openai',\n baseUrl: 'https://api.together.xyz/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: '...',\n models: [\n { id: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', label: 'meta-llama/Llama-3.3-70B-Instruct-Turbo' },\n { id: 'deepseek-ai/DeepSeek-V3', label: 'deepseek-ai/DeepSeek-V3' },\n { id: 'Qwen/Qwen2.5-72B-Instruct-Turbo', label: 'Qwen/Qwen2.5-72B-Instruct-Turbo' },\n ],\n },\n {\n id: 'fireworks',\n label: 'Fireworks',\n color: '#f97316',\n protocol: 'openai',\n baseUrl: 'https://api.fireworks.ai/inference/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: '...',\n models: [\n { id: 'accounts/fireworks/models/llama-v3p3-70b-instruct', label: 'accounts/fireworks/models/llama-v3p3-70b-instruct' },\n { id: 'accounts/fireworks/models/deepseek-v3', label: 'accounts/fireworks/models/deepseek-v3' },\n ],\n },\n {\n id: 'doubao',\n label: '豆包 / 火山方舟',\n color: '#1677ff',\n protocol: 'openai',\n baseUrl: 'https://ark.volces.com/api/v3',\n endpointPath: OPENAI_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: '...',\n models: [\n { id: 'doubao-pro-32k', label: 'doubao-pro-32k' },\n { id: 'doubao-lite-32k', label: 'doubao-lite-32k' },\n ],\n },\n {\n id: 'minimax',\n label: 'MiniMax',\n color: '#ff6b6b',\n protocol: 'minimax',\n baseUrl: 'https://api.minimax.chat/v1',\n endpointPath: MINIMAX_PATH,\n authMode: 'bearer',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: '...',\n models: [\n { id: 'MiniMax-Text-01', label: 'MiniMax-Text-01' },\n { id: 'abab6.5s-chat', label: 'abab6.5s-chat' },\n ],\n },\n {\n id: 'ollama',\n label: 'Ollama 本地',\n color: '#222222',\n protocol: 'openai',\n baseUrl: 'http://127.0.0.1:11434/v1',\n endpointPath: OPENAI_PATH,\n authMode: 'none',\n modelPlacement: 'body',\n builtin: true,\n keyPlaceholder: '',\n models: [\n { id: 'qwen2.5:7b', label: 'qwen2.5:7b' },\n { id: 'llama3.1:8b', label: 'llama3.1:8b' },\n { id: 'deepseek-r1:8b', label: 'deepseek-r1:8b' },\n ],\n },\n];\n\nexport function buildCiyuanProviderMap(customProviders: CiyuanProviderConfig[] = []) {\n return [...BUILTIN_CIYUAN_PROVIDERS, ...customProviders].reduce>(\n (acc, provider) => {\n acc[provider.id] = provider;\n return acc;\n },\n {}\n );\n}\n\nexport function getDefaultCiyuanProviderId() {\n return 'deepseek';\n}\n\nexport function getDefaultModelId(provider?: CiyuanProviderConfig | null) {\n return provider?.models[0]?.id ?? '';\n}\n\nexport function createProviderId(name: string) {\n const base = name\n .toLowerCase()\n .replace(/[^\\w\\u4e00-\\u9fa5-]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '') || 'custom-provider';\n return `custom-${base}-${Math.random().toString(36).slice(2, 8)}`;\n}\n"}}}}