From bc46eba8f69a9de687c4eff7ee4df30e77174be9 Mon Sep 17 00:00:00 2001
From: Diego Rodrigues de Sa e Souza
<8016841+diegosouzapw@users.noreply.github.com>
Date: Sun, 31 May 2026 08:26:47 -0300
Subject: [PATCH] Merge pull request #2975 from
xz-dev/feat/siliconflow-cn-endpoint-selector
feat(providers): add SiliconFlow endpoint selector
---
open-sse/executors/default.ts | 4 +
.../dashboard/providers/[id]/page.tsx | 131 ++++++++++++++++--
tests/unit/executor-default-base.test.ts | 11 ++
3 files changed, 131 insertions(+), 15 deletions(-)
diff --git a/open-sse/executors/default.ts b/open-sse/executors/default.ts
index 491ea48e75..3dd2ac39af 100644
--- a/open-sse/executors/default.ts
+++ b/open-sse/executors/default.ts
@@ -201,6 +201,10 @@ export class DefaultExecutor extends BaseExecutor {
const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl;
return buildMaritalkChatUrl(baseUrl);
}
+ case "siliconflow": {
+ const baseUrl = credentials?.providerSpecificData?.baseUrl || this.config.baseUrl;
+ return normalizeOpenAIChatUrl(baseUrl);
+ }
case "lm-studio":
case "modal":
case "reka":
diff --git a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx
index 44b672c032..4271047502 100644
--- a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx
+++ b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx
@@ -788,6 +788,7 @@ interface AddApiKeyModalProps {
isOpen: boolean;
provider?: string;
providerName?: string;
+ initialBaseUrl?: string;
isCompatible?: boolean;
isAnthropic?: boolean;
isCcCompatible?: boolean;
@@ -821,6 +822,11 @@ type CommandCodeAuthFlowState = {
message?: string;
};
+const SILICONFLOW_ENDPOINTS = [
+ { id: "siliconflow", label: "Global", baseUrl: "https://api.siliconflow.com/v1" },
+ { id: "siliconflow-cn", label: "China", baseUrl: "https://api.siliconflow.cn/v1" },
+] as const;
+
interface EditConnectionModalConnection {
id?: string;
name?: string;
@@ -1361,6 +1367,8 @@ export default function ProviderDetailPage() {
const [showOAuthModal, _setShowOAuthModal] = useState(false);
const [reauthConnection, setReauthConnection] = useState(null);
const [showAddApiKeyModal, setShowAddApiKeyModal] = useState(false);
+ const [showSiliconFlowEndpointModal, setShowSiliconFlowEndpointModal] = useState(false);
+ const [siliconFlowInitialBaseUrl, setSiliconFlowInitialBaseUrl] = useState();
const [showRiskNoticeModal, setShowRiskNoticeModal] = useState(false);
const [commandCodeAuthState, setCommandCodeAuthState] = useState({
phase: "idle",
@@ -1959,13 +1967,21 @@ export default function ProviderDetailPage() {
setShowOAuthModal(false);
}, [fetchConnections]);
+ const openApiKeyAddFlow = useCallback(() => {
+ if (providerId === "siliconflow") {
+ setShowSiliconFlowEndpointModal(true);
+ return;
+ }
+ setShowAddApiKeyModal(true);
+ }, [providerId]);
+
const openPrimaryAddFlow = useCallback(() => {
if (isOAuth) {
setShowOAuthModal(true);
return;
}
- setShowAddApiKeyModal(true);
- }, [isOAuth]);
+ openApiKeyAddFlow();
+ }, [isOAuth, openApiKeyAddFlow]);
const gateConnectionFlow = useCallback(
(callback: () => void) => {
@@ -2008,6 +2024,7 @@ export default function ProviderDetailPage() {
const handleCloseAddApiKeyModal = useCallback(() => {
clearCommandCodeAuthTimer();
+ setSiliconFlowInitialBaseUrl(undefined);
commandCodeAuthWindowRef.current?.close?.();
commandCodeAuthWindowRef.current = null;
setCommandCodeAuthState({
@@ -2255,6 +2272,7 @@ export default function ProviderDetailPage() {
const newConnection = connectionData?.connection;
await fetchConnections();
setShowAddApiKeyModal(false);
+ setSiliconFlowInitialBaseUrl(undefined);
// For Gemini: show progress dialog and sync models from endpoint
if (providerId === "gemini" && newConnection?.id) {
@@ -3915,11 +3933,7 @@ export default function ProviderDetailPage() {
-