This is an automated email from the ASF dual-hosted git repository.

hsluoyz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/casbin-gateway.git


The following commit(s) were added to refs/heads/master by this push:
     new 66ed225  fix(provider): surface base URL entry for custom providers
66ed225 is described below

commit 66ed225d73b90d6bc3ce95aac2510981ea751db8
Author: Yang Luo <[email protected]>
AuthorDate: Thu Sep 3 23:10:31 2026 +0800

    fix(provider): surface base URL entry for custom providers
---
 web/src/components/shared/simple-select.tsx | 16 +++++------
 web/src/locales/en/data.json                |  3 ++-
 web/src/locales/zh/data.json                |  3 ++-
 web/src/pages/ProviderListPage.tsx          | 41 +++++++++++++++++++++--------
 4 files changed, 41 insertions(+), 22 deletions(-)

diff --git a/web/src/components/shared/simple-select.tsx 
b/web/src/components/shared/simple-select.tsx
index fdc50c3..61319e3 100644
--- a/web/src/components/shared/simple-select.tsx
+++ b/web/src/components/shared/simple-select.tsx
@@ -156,16 +156,14 @@ export function SearchSelect({
             placeholder={searchPlaceholder ?? i18next.t("general:Search")}
           />
           <CommandList>
-            <CommandEmpty>
-              {allowCustomValue && search !== "" ? (
-                <button type="button" className="hover:text-foreground w-full 
px-2" onClick={() => pick(search)}>
-                  {search}
-                </button>
-              ) : (
-                (emptyText ?? i18next.t("general:No data"))
-              )}
-            </CommandEmpty>
+            <CommandEmpty>{emptyText ?? i18next.t("general:No 
data")}</CommandEmpty>
             <CommandGroup>
+              {allowCustomValue && search !== "" && !items.some(option => 
option.value === search) ? (
+                <CommandItem value={search} onSelect={() => pick(search)}>
+                  <Check className="size-4 opacity-0" />
+                  {search}
+                </CommandItem>
+              ) : null}
               {items.map(option => (
                 <CommandItem key={option.value} value={String(option.label)} 
onSelect={() => pick(option.value)}>
                   <Check className={cn("size-4", option.value === value ? 
"opacity-100" : "opacity-0")} />
diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json
index b0973de..9b07b9a 100644
--- a/web/src/locales/en/data.json
+++ b/web/src/locales/en/data.json
@@ -739,6 +739,7 @@
     "Balance unavailable": "Balance unavailable",
     "Base URL": "Base URL",
     "Base URL hint": "Requests will be sent to",
+    "Custom base URL hint": "The endpoint of your relay or self-hosted 
service, e.g. https://your-relay.com/v1";,
     "Caller's own login": "The caller's own login",
     "Change source": "Change",
     "Claude subscription": "Claude subscription",
@@ -749,7 +750,7 @@
     "Connection Failed": "Connection Failed",
     "Connection Successful": "Connection Successful",
     "Connectivity": "Connectivity",
-    "Connectivity hint": "A read-only probe against the upstream, which costs 
nothing and answers whether this key works. It also runs once when the form is 
submitted.",
+    "Connectivity hint": "A real request to the upstream: the first model is 
asked for one short answer, so a key that does not work, or a model the 
upstream will not serve, is caught here. It costs a few tokens. It also runs 
once when the form is submitted.",
     "Continue draft": "Continue draft",
     "Cooling down": "Cooling down",
     "Currency": "Currency",
diff --git a/web/src/locales/zh/data.json b/web/src/locales/zh/data.json
index 2f2c47a..99c73df 100644
--- a/web/src/locales/zh/data.json
+++ b/web/src/locales/zh/data.json
@@ -760,6 +760,7 @@
     "Balance unavailable": "无法获取余额",
     "Base URL": "基础 URL",
     "Base URL hint": "实际请求将发往",
+    "Custom base URL hint": "中转站或自建服务的接口地址,例如 https://your-relay.com/v1";,
     "Caller's own login": "调用方自己的登录",
     "Change source": "更换",
     "Claude subscription": "Claude 订阅登录",
@@ -770,7 +771,7 @@
     "Connection Failed": "连接失败",
     "Connection Successful": "连接成功",
     "Connectivity": "连通性",
-    "Connectivity hint": "对上游做一次只读探测,不产生费用,用来确认这个密钥是否可用。提交表单时也会自动探测一次。",
+    "Connectivity hint": 
"向上游发起一次真实请求:用第一个模型问一句话,因此密钥不可用、或上游不提供该模型时都能在这里发现。会消耗少量 token。提交表单时也会自动探测一次。",
     "Continue draft": "继续草稿",
     "Cooling down": "冷却中",
     "Currency": "币种",
diff --git a/web/src/pages/ProviderListPage.tsx 
b/web/src/pages/ProviderListPage.tsx
index 41688d7..cd09a79 100644
--- a/web/src/pages/ProviderListPage.tsx
+++ b/web/src/pages/ProviderListPage.tsx
@@ -557,6 +557,23 @@ export default function ProviderListPage({account}: 
{account: Account}) {
                 </Button>
               </div>
             </Field>
+            {source.key === customSource ? (
+              <Field
+                label={i18next.t("provider:Base URL")}
+                htmlFor="provider-base-url"
+                className="md:col-span-2"
+                hint={i18next.t("provider:Custom base URL hint")}
+              >
+                <SearchSelect
+                  allowCustomValue
+                  id="provider-base-url"
+                  value={form.baseUrl}
+                  placeholder={baseUrlPlaceholder(form.type)}
+                  options={baseUrlPresets(form.type)}
+                  onChange={value => setFormField("baseUrl", value)}
+                />
+              </Field>
+            ) : null}
             <Field
               label={i18next.t("general:Name")}
               htmlFor="provider-display-name"
@@ -628,7 +645,7 @@ export default function ProviderListPage({account}: 
{account: Account}) {
                 onChange={event => setFormField("notes", event.target.value)}
               />
             </Field>
-            <Advanced key={source.key} defaultOpen={source.key === 
customSource}>
+            <Advanced key={source.key} defaultOpen={false}>
               <Field label={i18next.t("provider:Type")}>
                 <SimpleSelect
                   value={form.type}
@@ -640,16 +657,18 @@ export default function ProviderListPage({account}: 
{account: Account}) {
                   ]}
                 />
               </Field>
-              <Field label={i18next.t("provider:Base URL")} 
htmlFor="provider-base-url">
-                <SearchSelect
-                  allowCustomValue
-                  id="provider-base-url"
-                  value={form.baseUrl}
-                  placeholder={baseUrlPlaceholder(form.type)}
-                  options={baseUrlPresets(form.type)}
-                  onChange={value => setFormField("baseUrl", value)}
-                />
-              </Field>
+              {source.key === customSource ? null : (
+                <Field label={i18next.t("provider:Base URL")} 
htmlFor="provider-base-url">
+                  <SearchSelect
+                    allowCustomValue
+                    id="provider-base-url"
+                    value={form.baseUrl}
+                    placeholder={baseUrlPlaceholder(form.type)}
+                    options={baseUrlPresets(form.type)}
+                    onChange={value => setFormField("baseUrl", value)}
+                  />
+                </Field>
+              )}
               <Field
                 label={i18next.t("provider:Authentication")}
                 hint={usesClientAuth(form) ? i18next.t("provider:Client auth 
hint") : undefined}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to