feat: add siliconflow chat provider (#4764) * feat: add siliconflow chat provider * fix: remove siliconflow seed handling * fix: enable SiliconFlow image inlining from shared vision list * fix: handle SiliconFlow model context limits and sizing * fix: drop SiliconFlow reasoning effort handling since controls are hidden * fix: parse SiliconFlow reasoning in streaming and non-streaming * fix: add missing comma in supported models list * Remove seed from HTML template * Combine streamed reasoning parsing blocks * Update logo image * Unhide image inlining controls --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>

5c974bd14810a56b762c606681e7bfd995d88340

QiyuanChen <72334646+qychen2001@users.noreply.github.com>

Signed
11 files changed, +166 -8Ignore whitespace
public/img/siliconflow.svg+4 -0
@@ -0,0 +1,4 @@
1+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+<svg width="142.22" height="68.010002" viewBox="0 0 142.22 68.010002" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
3+ <path d="M 136.05,0 H 74.21 c -3.42,0 -6.18,2.77 -6.18,6.18 v 18.55 c 0,3.42 -2.77,6.18 -6.18,6.18 H 6.18 C 2.76,30.91 0,33.68 0,37.09 v 24.74 c 0,3.42 2.77,6.18 6.18,6.18 h 61.84 c 3.42,0 6.18,-2.77 6.18,-6.18 V 43.28 c 0,-3.42 2.77,-6.18 6.18,-6.18 h 55.66 c 3.42,0 6.18,-2.77 6.18,-6.18 V 6.18 C 142.22,2.76 139.45,0 136.04,0 Z" />
4+</svg>
public/index.html+22 -7
@@ -693,7 +693,7 @@
693693 </span>
694694 </div>
695695 </div>
696696 <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,siliconflow,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai,zai">
697697 <div class="range-block-title" data-i18n="Temperature">
698698 Temperature
699699 </div>
@@ -706,7 +706,7 @@
706706 </div>
707707 </div>
708708 </div>
709709 <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,siliconflow,mistralai,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai">
710710 <div class="range-block-title" data-i18n="Frequency Penalty">
711711 Frequency Penalty
712712 </div>
@@ -719,7 +719,7 @@
719719 </div>
720720 </div>
721721 </div>
722722 <div class="range-block" data-source="openai,aimlapi,openrouter,custom,cohere,perplexity,groq,siliconflow,mistralai,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai">
723723 <div class="range-block-title" data-i18n="Presence Penalty">
724724 Presence Penalty
725725 </div>
@@ -745,7 +745,7 @@
745745 </div>
746746 </div>
747747 </div>
748748 <div class="range-block" data-source="openai,claude,aimlapi,openrouter,ai21,makersuite,vertexai,mistralai,custom,cohere,perplexity,groq,siliconflow,electronhub,nanogpt,deepseek,xai,pollinations,moonshot,fireworks,cometapi,azure_openai,zai">
749749 <div class="range-block-title" data-i18n="Top P">
750750 Top P
751751 </div>
@@ -1965,7 +1965,7 @@
19651965 </b>
19661966 </div>
19671967 </div>
19681968 <div class="range-block" data-source="openai,cohere,mistralai,custom,claude,aimlapi,openrouter,groq,siliconflow,deepseek,makersuite,vertexai,ai21,xai,pollinations,moonshot,fireworks,cometapi,electronhub,azure_openai,zai">
19691969 <label for="openai_function_calling" class="checkbox_label flexWrap widthFreeExpand">
19701970 <input id="openai_function_calling" type="checkbox" />
19711971 <span data-i18n="Enable function calling">Enable function calling</span>
@@ -1980,7 +1980,7 @@
19801980 <strong data-i18n="enable_functions_desc_4">Not supported when Prompt Post-Processing with "no tools" is used!</strong>
19811981 </div>
19821982 </div>
19831983 <div class="range-block" data-source="openai,aimlapi,openrouter,mistralai,makersuite,vertexai,claude,custom,xai,pollinations,moonshot,cohere,cometapi,nanogpt,electronhub,azure_openai,zai,siliconflow">
19841984 <label for="openai_image_inlining" class="checkbox_label flexWrap widthFreeExpand">
19851985 <input id="openai_image_inlining" type="checkbox" />
19861986 <span data-i18n="Send inline images">Send inline images</span>
@@ -1992,7 +1992,7 @@
19921992 <div id="image_inlining_hint" class="flexBasis100p toggle-description justifyLeft">
19931993 <span data-i18n="image_inlining_hint_1">Sends images in prompts if the model supports it.</span>
19941994 </div>
19951995 <div class="flex-container flexFlowColumn wide100p textAlignCenter marginTop10" data-source="openai,custom,xai,pollinations,cohere,cometapi,nanogpt,moonshot,aimlapi,openrouter,mistralai,electronhub,azure_openai,zai,siliconflow">
19961996 <div class="flex-container oneline-dropdown">
19971997 <label for="openai_inline_image_quality" data-i18n="Inline Image Quality">
19981998 Inline Image Quality
@@ -2806,6 +2806,7 @@
28062806 <option value="openrouter">OpenRouter</option>
28072807 <option value="perplexity">Perplexity</option>
28082808 <option value="pollinations">Pollinations</option>
2809+ <option value="siliconflow">SiliconFlow</option>
28092810 <option value="xai">xAI (Grok)</option>
28102811 <option value="zai">Z.AI (GLM)</option>
28112812 </optgroup>
@@ -3397,6 +3398,20 @@
33973398 <option value="mistral-saba-24b">mistral-saba-24b</option>
33983399 </select>
33993400 </div>
3401+ <div id="siliconflow_form" data-source="siliconflow">
3402+ <h4>SiliconFlow API Key</h4>
3403+ <div class="flex-container">
3404+ <input id="api_key_siliconflow" name="api_key_siliconflow" class="text_pole flex1" value="" type="text" autocomplete="off">
3405+ <div title="Manage API keys" data-i18n="[title]Manage API keys" class="menu_button fa-solid fa-key fa-fw manage-api-keys" data-key="api_key_siliconflow"></div>
3406+ </div>
3407+ <div data-for="api_key_siliconflow" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you click 'Connect'.">
3408+ For privacy reasons, your API key will be hidden after you click 'Connect'.
3409+ </div>
3410+ <h4>SiliconFlow Model</h4>
3411+ <select id="model_siliconflow_select">
3412+ <option value="" data-i18n="-- Connect to the API --">-- Connect to the API --</option>
3413+ </select>
3414+ </div>
34003415 <div id="electronhub_form" data-source="electronhub">
34013416 <h4 data-i18n="Electron Hub API Key">Electron Hub API Key</h4>
34023417 <div>
public/scripts/RossAscends-mods.js+1 -0
@@ -403,6 +403,7 @@ function RA_autoconnect(PrevApi) {
403403 || (secret_state[SECRET_KEYS.COHERE] && oai_settings.chat_completion_source == chat_completion_sources.COHERE)
404404 || (secret_state[SECRET_KEYS.PERPLEXITY] && oai_settings.chat_completion_source == chat_completion_sources.PERPLEXITY)
405405 || (secret_state[SECRET_KEYS.GROQ] && oai_settings.chat_completion_source == chat_completion_sources.GROQ)
406+ || (secret_state[SECRET_KEYS.SILICONFLOW] && oai_settings.chat_completion_source == chat_completion_sources.SILICONFLOW)
406407 || (secret_state[SECRET_KEYS.ELECTRONHUB] && oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB)
407408 || (secret_state[SECRET_KEYS.NANOGPT] && oai_settings.chat_completion_source == chat_completion_sources.NANOGPT)
408409 || (secret_state[SECRET_KEYS.DEEPSEEK] && oai_settings.chat_completion_source == chat_completion_sources.DEEPSEEK)
public/scripts/openai.js+118 -1
@@ -194,6 +194,7 @@ export const chat_completion_sources = {
194194 COMETAPI: 'cometapi',
195195 AZURE_OPENAI: 'azure_openai',
196196 ZAI: 'zai',
197+ SILICONFLOW: 'siliconflow',
197198};
198199
199200const character_names_behavior = {
@@ -280,6 +281,7 @@ export const settingsToUpdate = {
280281 cohere_model: ['#model_cohere_select', 'cohere_model', false, true],
281282 perplexity_model: ['#model_perplexity_select', 'perplexity_model', false, true],
282283 groq_model: ['#model_groq_select', 'groq_model', false, true],
284+ siliconflow_model: ['#model_siliconflow_select', 'siliconflow_model', false, true],
283285 electronhub_model: ['#model_electronhub_select', 'electronhub_model', false, true],
284286 electronhub_sort_models: ['#electronhub_sort_models', 'electronhub_sort_models', false, true],
285287 electronhub_group_models: ['#electronhub_group_models', 'electronhub_group_models', false, true],
@@ -387,6 +389,7 @@ const default_settings = {
387389 cohere_model: 'command-r-plus',
388390 perplexity_model: 'sonar-pro',
389391 groq_model: 'llama-3.3-70b-versatile',
392+ siliconflow_model: 'deepseek-ai/DeepSeek-V3',
390393 electronhub_model: 'gpt-4o-mini',
391394 electronhub_sort_models: 'alphabetically',
392395 electronhub_group_models: false,
@@ -1587,6 +1590,8 @@ export function getChatCompletionModel(source = null) {
15871590 return oai_settings.perplexity_model;
15881591 case chat_completion_sources.GROQ:
15891592 return oai_settings.groq_model;
1593+ case chat_completion_sources.SILICONFLOW:
1594+ return oai_settings.siliconflow_model;
15901595 case chat_completion_sources.ELECTRONHUB:
15911596 return oai_settings.electronhub_model;
15921597 case chat_completion_sources.NANOGPT:
@@ -1920,6 +1925,24 @@ function saveModelList(data) {
19201925 $('#model_groq_select').val(oai_settings.groq_model).trigger('change');
19211926 }
19221927
1928+ if (oai_settings.chat_completion_source === chat_completion_sources.SILICONFLOW) {
1929+ $('#model_siliconflow_select').empty();
1930+ model_list.forEach((model) => {
1931+ $('#model_siliconflow_select').append(
1932+ $('<option>', {
1933+ value: model.id,
1934+ text: model.id,
1935+ }));
1936+ });
1937+
1938+ const selectedModel = model_list.find(model => model.id === oai_settings.siliconflow_model);
1939+ if (model_list.length > 0 && (!selectedModel || !oai_settings.siliconflow_model)) {
1940+ oai_settings.siliconflow_model = model_list[0].id;
1941+ }
1942+
1943+ $('#model_siliconflow_select').val(oai_settings.siliconflow_model).trigger('change');
1944+ }
1945+
19231946 if (oai_settings.chat_completion_source === chat_completion_sources.FIREWORKS) {
19241947 $('#model_fireworks_select').empty();
19251948 model_list.forEach((model) => {
@@ -2654,7 +2677,7 @@ export function getStreamingReply(data, state, { chatCompletionSource = null, ov
26542677 state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || '');
26552678 }
26562679 return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? '';
26572680 } else if ([chat_completion_sources.CUSTOM, chat_completion_sources.POLLINATIONS, chat_completion_sources.AIMLAPI, chat_completion_sources.MOONSHOT, chat_completion_sources.COMETAPI, chat_completion_sources.ELECTRONHUB, chat_completion_sources.NANOGPT, chat_completion_sources.ZAI, chat_completion_sources.SILICONFLOW].includes(chat_completion_source)) {
26582681 if (show_thoughts) {
26592682 state.reasoning +=
26602683 data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content ??
@@ -3665,6 +3688,7 @@ function loadOpenAISettings(data, settings) {
36653688 oai_settings.cohere_model = settings.cohere_model ?? default_settings.cohere_model;
36663689 oai_settings.perplexity_model = settings.perplexity_model ?? default_settings.perplexity_model;
36673690 oai_settings.groq_model = settings.groq_model ?? default_settings.groq_model;
3691+ oai_settings.siliconflow_model = settings.siliconflow_model ?? default_settings.siliconflow_model;
36683692 oai_settings.electronhub_model = settings.electronhub_model ?? default_settings.electronhub_model;
36693693 oai_settings.electronhub_sort_models = settings.electronhub_sort_models ?? default_settings.electronhub_sort_models;
36703694 oai_settings.electronhub_group_models = settings.electronhub_group_models ?? default_settings.electronhub_group_models;
@@ -3770,6 +3794,8 @@ function loadOpenAISettings(data, settings) {
37703794 $(`#model_perplexity_select option[value="${oai_settings.perplexity_model}"`).prop('selected', true);
37713795 $('#model_groq_select').val(oai_settings.groq_model);
37723796 $(`#model_groq_select option[value="${oai_settings.groq_model}"`).prop('selected', true);
3797+ $('#model_siliconflow_select').val(oai_settings.siliconflow_model);
3798+ $(`#model_siliconflow_select option[value="${oai_settings.siliconflow_model}"`).prop('selected', true);
37733799 $('#model_electronhub_select').val(oai_settings.electronhub_model);
37743800 $(`#model_electronhub_select option[value="${oai_settings.electronhub_model}"`).prop('selected', true);
37753801 $('#model_nanogpt_select').val(oai_settings.nanogpt_model);
@@ -4077,6 +4103,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
40774103 cohere_model: settings.cohere_model,
40784104 perplexity_model: settings.perplexity_model,
40794105 groq_model: settings.groq_model,
4106+ siliconflow_model: settings.siliconflow_model,
40804107 xai_model: settings.xai_model,
40814108 pollinations_model: settings.pollinations_model,
40824109 aimlapi_model: settings.aimlapi_model,
@@ -4766,6 +4793,65 @@ function getZaiMaxContext(model, isUnlocked) {
47664793}
47674794
47684795/**
4796+ * Get the maximum context size for the SiliconFlow model
4797+ * @param {string} model Model identifier
4798+ * @param {boolean} isUnlocked Whether context limits are unlocked
4799+ * @returns {number} Maximum context size in tokens
4800+ */
4801+function getSiliconflowMaxContext(model, isUnlocked) {
4802+ if (isUnlocked) {
4803+ return unlocked_max;
4804+ }
4805+
4806+ const contextMap = {
4807+ 'baidu/ERNIE-4.5-300B-A47B': max_128k,
4808+ 'ByteDance-Seed/Seed-OSS-36B-Instruct': max_256k,
4809+ 'deepseek-ai/DeepSeek-R1': max_128k,
4810+ 'deepseek-ai/DeepSeek-V3': max_128k,
4811+ 'deepseek-ai/DeepSeek-V3.1': max_128k,
4812+ 'deepseek-ai/DeepSeek-V3.1-Terminus': max_128k,
4813+ 'deepseek-ai/DeepSeek-V3.2-Exp': max_128k,
4814+ 'deepseek-ai/deepseek-vl2': max_4k,
4815+ 'inclusionAI/Ling-1T': max_128k,
4816+ 'inclusionAI/Ling-flash-2.0': max_128k,
4817+ 'inclusionAI/Ling-mini-2.0': max_128k,
4818+ 'inclusionAI/Ring-1T': max_128k,
4819+ 'inclusionAI/Ring-flash-2.0': max_128k,
4820+ 'meta-llama/Llama-3.3-70B-Instruct': max_32k,
4821+ 'meta-llama/Meta-Llama-3.1-8B-Instruct': max_32k,
4822+ 'MiniMaxAI/MiniMax-M1-80k': max_128k,
4823+ 'MiniMaxAI/MiniMax-M2': max_128k,
4824+ 'moonshotai/Kimi-K2-Instruct': max_128k,
4825+ 'moonshotai/Kimi-K2-Instruct-0905': max_256k,
4826+ 'moonshotai/Kimi-K2-Thinking': max_256k,
4827+ 'openai/gpt-oss-120b': max_128k,
4828+ 'openai/gpt-oss-20b': max_128k,
4829+ 'Qwen/Qwen3-235B-A22B-Instruct-2507': max_256k,
4830+ 'Qwen/Qwen3-235B-A22B-Thinking-2507': max_256k,
4831+ 'Qwen/Qwen3-30B-A3B-Instruct-2507': max_256k,
4832+ 'Qwen/Qwen3-30B-A3B-Thinking-2507': max_256k,
4833+ 'Qwen/Qwen3-VL-235B-A22B-Instruct': max_256k,
4834+ 'Qwen/Qwen3-VL-235B-A22B-Thinking': max_256k,
4835+ 'Qwen/Qwen3-VL-30B-A3B-Instruct': max_256k,
4836+ 'Qwen/Qwen3-VL-30B-A3B-Thinking': max_256k,
4837+ 'Qwen/Qwen3-VL-32B-Instruct': max_256k,
4838+ 'Qwen/Qwen3-VL-32B-Thinking': max_256k,
4839+ 'Qwen/Qwen3-VL-8B-Instruct': max_256k,
4840+ 'Qwen/Qwen3-VL-8B-Thinking': max_256k,
4841+ 'stepfun-ai/step3': max_64k,
4842+ 'tencent/Hunyuan-A13B-Instruct': max_128k,
4843+ 'zai-org/GLM-4.5': max_128k,
4844+ 'zai-org/GLM-4.5-Air': max_128k,
4845+ 'zai-org/GLM-4.5V': max_64k,
4846+ 'zai-org/GLM-4.6': max_200k,
4847+ };
4848+
4849+ // Return context size if model found, otherwise default to 32k
4850+ return Object.entries(contextMap).find(([key]) => model.includes(key))?.[1] || max_32k;
4851+
4852+}
4853+
4854+/**
47694855 * Get the maximum context size for the Moonshot model
47704856 * @param {string} model Model identifier
47714857 * @param {boolean} isUnlocked If context limits are unlocked
@@ -4956,6 +5042,15 @@ async function onModelChange() {
49565042 oai_settings.groq_model = value;
49575043 }
49585044
5045+ if ($(this).is('#model_siliconflow_select')) {
5046+ if (!value) {
5047+ console.debug('Null SiliconFlow model selected. Ignoring.');
5048+ return;
5049+ }
5050+ console.log('SiliconFlow model changed to', value);
5051+ oai_settings.siliconflow_model = value;
5052+ }
5053+
49595054 if ($(this).is('#model_electronhub_select')) {
49605055 if (!value) {
49615056 console.debug('Null ElectronHub model selected. Ignoring.');
@@ -5356,6 +5451,15 @@ async function onModelChange() {
53565451 $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
53575452 }
53585453
5454+ if (oai_settings.chat_completion_source === chat_completion_sources.SILICONFLOW) {
5455+ const maxContext = getSiliconflowMaxContext(oai_settings.siliconflow_model, oai_settings.max_context_unlocked);
5456+ $('#openai_max_context').attr('max', maxContext);
5457+ oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context);
5458+ $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
5459+ oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai);
5460+ $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
5461+ }
5462+
53595463 if (oai_settings.chat_completion_source == chat_completion_sources.ZAI) {
53605464 const maxContext = getZaiMaxContext(oai_settings.zai_model, oai_settings.max_context_unlocked);
53615465 $('#openai_max_context').attr('max', maxContext);
@@ -5411,6 +5515,7 @@ async function onConnectButtonClick(e) {
54115515 [chat_completion_sources.COHERE]: { key: SECRET_KEYS.COHERE, selector: '#api_key_cohere', proxy: false },
54125516 [chat_completion_sources.PERPLEXITY]: { key: SECRET_KEYS.PERPLEXITY, selector: '#api_key_perplexity', proxy: false },
54135517 [chat_completion_sources.GROQ]: { key: SECRET_KEYS.GROQ, selector: '#api_key_groq', proxy: false },
5518+ [chat_completion_sources.SILICONFLOW]: { key: SECRET_KEYS.SILICONFLOW, selector: '#api_key_siliconflow', proxy: false },
54145519 [chat_completion_sources.ELECTRONHUB]: { key: SECRET_KEYS.ELECTRONHUB, selector: '#api_key_electronhub', proxy: false },
54155520 [chat_completion_sources.NANOGPT]: { key: SECRET_KEYS.NANOGPT, selector: '#api_key_nanogpt', proxy: false },
54165521 [chat_completion_sources.DEEPSEEK]: { key: SECRET_KEYS.DEEPSEEK, selector: '#api_key_deepseek', proxy: true },
@@ -5493,6 +5598,9 @@ function toggleChatCompletionForms() {
54935598 else if (oai_settings.chat_completion_source == chat_completion_sources.GROQ) {
54945599 $('#model_groq_select').trigger('change');
54955600 }
5601+ else if (oai_settings.chat_completion_source == chat_completion_sources.SILICONFLOW) {
5602+ $('#model_siliconflow_select').trigger('change');
5603+ }
54965604 else if (oai_settings.chat_completion_source == chat_completion_sources.ELECTRONHUB) {
54975605 $('#model_electronhub_select').trigger('change');
54985606 }
@@ -5647,6 +5755,12 @@ export function isImageInliningSupported() {
56475755 'moonshot-v1-128k-vision-preview',
56485756 // Z.AI (GLM)
56495757 'glm-4.5v',
5758+ // SiliconFlow
5759+ 'Qwen/Qwen3-VL-32B-Instruct',
5760+ 'Qwen/Qwen3-VL-8B-Instruct',
5761+ 'Qwen/Qwen3-VL-235B-A22B-Instruct',
5762+ 'Qwen/Qwen3-VL-30B-A3B-Instruct',
5763+ 'zai-org/GLM-4.5V',
56505764 ];
56515765
56525766 switch (oai_settings.chat_completion_source) {
@@ -5691,6 +5805,8 @@ export function isImageInliningSupported() {
56915805 return (Array.isArray(model_list) && model_list.find(m => m.id === oai_settings.nanogpt_model)?.capabilities?.vision);
56925806 case chat_completion_sources.ZAI:
56935807 return visionSupportedModels.some(model => oai_settings.zai_model.includes(model));
5808+ case chat_completion_sources.SILICONFLOW:
5809+ return visionSupportedModels.some(model => oai_settings.siliconflow_model.includes(model));
56945810 default:
56955811 return false;
56965812 }
@@ -6571,6 +6687,7 @@ export function initOpenAI() {
65716687 $('#model_cohere_select').on('change', onModelChange);
65726688 $('#model_perplexity_select').on('change', onModelChange);
65736689 $('#model_groq_select').on('change', onModelChange);
6690+ $('#model_siliconflow_select').on('change', onModelChange);
65746691 $('#model_electronhub_select').on('change', onModelChange);
65756692 $('#model_nanogpt_select').on('change', onModelChange);
65766693 $('#model_deepseek_select').on('change', onModelChange);
public/scripts/reasoning.js+1 -0
@@ -127,6 +127,7 @@ export function extractReasoningFromData(data, {
127127 case chat_completion_sources.COMETAPI:
128128 case chat_completion_sources.ELECTRONHUB:
129129 case chat_completion_sources.NANOGPT:
130+ case chat_completion_sources.SILICONFLOW:
130131 case chat_completion_sources.ZAI:
131132 case chat_completion_sources.CUSTOM: {
132133 return data?.choices?.[0]?.message?.reasoning_content
public/scripts/secrets.js+3 -0
@@ -69,6 +69,7 @@ export const SECRET_KEYS = {
6969 MOONSHOT: 'api_key_moonshot',
7070 COMETAPI: 'api_key_cometapi',
7171 ZAI: 'api_key_zai',
72+ SILICONFLOW: 'api_key_siliconflow',
7273};
7374
7475const FRIENDLY_NAMES = {
@@ -126,6 +127,7 @@ const FRIENDLY_NAMES = {
126127 [SECRET_KEYS.COMETAPI]: 'CometAPI',
127128 [SECRET_KEYS.AZURE_OPENAI]: 'Azure OpenAI',
128129 [SECRET_KEYS.ZAI]: 'Z.AI',
130+ [SECRET_KEYS.SILICONFLOW]: 'SiliconFlow',
129131};
130132
131133const INPUT_MAP = {
@@ -166,6 +168,7 @@ const INPUT_MAP = {
166168 [SECRET_KEYS.COMETAPI]: '#api_key_cometapi',
167169 [SECRET_KEYS.AZURE_OPENAI]: '#api_key_azure_openai',
168170 [SECRET_KEYS.ZAI]: '#api_key_zai',
171+ [SECRET_KEYS.SILICONFLOW]: '#api_key_siliconflow',
169172};
170173
171174const getLabel = () => moment().format('L LT');
public/scripts/slash-commands.js+1 -0
@@ -4844,6 +4844,7 @@ function getModelOptions(quiet) {
48444844 { id: 'model_cohere_select', api: 'openai', type: chat_completion_sources.COHERE },
48454845 { id: 'model_perplexity_select', api: 'openai', type: chat_completion_sources.PERPLEXITY },
48464846 { id: 'model_groq_select', api: 'openai', type: chat_completion_sources.GROQ },
4847+ { id: 'model_siliconflow_select', api: 'openai', type: chat_completion_sources.SILICONFLOW },
48474848 { id: 'model_electronhub_select', api: 'openai', type: chat_completion_sources.ELECTRONHUB },
48484849 { id: 'model_nanogpt_select', api: 'openai', type: chat_completion_sources.NANOGPT },
48494850 { id: 'model_deepseek_select', api: 'openai', type: chat_completion_sources.DEEPSEEK },
public/scripts/tool-calling.js+1 -0
@@ -662,6 +662,7 @@ export class ToolManager {
662662 chat_completion_sources.ELECTRONHUB,
663663 chat_completion_sources.AZURE_OPENAI,
664664 chat_completion_sources.ZAI,
665+ chat_completion_sources.SILICONFLOW,
665666 ];
666667 return supportedSources.includes(oai_settings.chat_completion_source);
667668 }
src/constants.js+1 -0
@@ -207,6 +207,7 @@ export const CHAT_COMPLETION_SOURCES = {
207207 COMETAPI: 'cometapi',
208208 AZURE_OPENAI: 'azure_openai',
209209 ZAI: 'zai',
210+ SILICONFLOW: 'siliconflow',
210211};
211212
212213/**
src/endpoints/backends/chat-completions.js+13 -0
@@ -76,6 +76,7 @@ const API_MOONSHOT = 'https://api.moonshot.ai/v1';
7676const API_FIREWORKS = 'https://api.fireworks.ai/inference/v1';
7777const API_COMETAPI = 'https://api.cometapi.com/v1';
7878const API_ZAI = 'https://api.z.ai/api/paas/v4';
79+const API_SILICONFLOW = 'https://api.siliconflow.com/v1';
7980
8081/**
8182 * Gets OpenRouter transforms based on the request.
@@ -1570,6 +1571,10 @@ router.post('/status', async function (request, statusResponse) {
15701571 console.error('Azure OpenAI status check connection error:', error);
15711572 return statusResponse.status(500).send({ error: true, message: 'Failed to connect to the Azure endpoint.' });
15721573 }
1574+ } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.SILICONFLOW) {
1575+ apiUrl = API_SILICONFLOW;
1576+ apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW);
1577+ headers = {};
15731578 } else {
15741579 console.warn('This chat completion source is not supported yet.');
15751580 return statusResponse.status(400).send({ error: true });
@@ -1980,6 +1985,14 @@ router.post('/generate', function (request, response) {
19801985 if (request.body.json_schema) {
19811986 setJsonObjectFormat(bodyParams, request.body.messages, request.body.json_schema);
19821987 }
1988+ } else if (request.body.chat_completion_source === CHAT_COMPLETION_SOURCES.SILICONFLOW) {
1989+ apiUrl = API_SILICONFLOW;
1990+ apiKey = readSecret(request.user.directories, SECRET_KEYS.SILICONFLOW);
1991+ headers = {};
1992+ bodyParams = {};
1993+ if (request.body.json_schema) {
1994+ setJsonObjectFormat(bodyParams, request.body.messages, request.body.json_schema);
1995+ }
19831996 } else {
19841997 console.warn('This chat completion source is not supported yet.');
19851998 return response.status(400).send({ error: true });
src/endpoints/secrets.js+1 -0
@@ -62,6 +62,7 @@ export const SECRET_KEYS = {
6262 COMETAPI: 'api_key_cometapi',
6363 AZURE_OPENAI: 'api_key_azure_openai',
6464 ZAI: 'api_key_zai',
65+ SILICONFLOW: 'api_key_siliconflow',
6566};
6667
6768/**