You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@casbin.apache.org by hs...@apache.org on 2026/08/23 09:07:34 UTC

(casbin-gateway) branch master updated: fix(ui): stop offering Codex a direct mode it cannot use

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 7696f22  fix(ui): stop offering Codex a direct mode it cannot use
7696f22 is described below

commit 7696f222fecef8a7af359b008a1640d823bd644f
Author: Yang Luo <hs...@gmail.com>
AuthorDate: Sun Aug 23 17:07:27 2026 +0800

    fix(ui): stop offering Codex a direct mode it cannot use
---
 web/src/components/ProviderCard.tsx | 25 +++++++++++++++++++------
 web/src/lib/agents.ts               |  9 +++++++++
 web/src/lib/providers.ts            |  5 +++++
 web/src/locales/en/data.json        |  3 ++-
 web/src/locales/zh/data.json        |  3 ++-
 5 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/web/src/components/ProviderCard.tsx b/web/src/components/ProviderCard.tsx
index 1967de7..92e632e 100644
--- a/web/src/components/ProviderCard.tsx
+++ b/web/src/components/ProviderCard.tsx
@@ -41,8 +41,14 @@ import {
   SelectValue,
 } from "@/components/ui/select";
 import {Switch} from "@/components/ui/switch";
-import {agentProxyBaseUrl, agentSetupNoteKey, directMode, gatewayMode} from "@/lib/agents";
-import {providerProtocol, shellForPath, usesClientAuth} from "@/lib/providers";
+import {
+  agentNeedsResponsesApi,
+  agentProxyBaseUrl,
+  agentSetupNoteKey,
+  directMode,
+  gatewayMode,
+} from "@/lib/agents";
+import {providerProtocol, servesResponsesApi, shellForPath, usesClientAuth} from "@/lib/providers";
 import {cn} from "@/lib/utils";
 import type {Agent, AgentProviderFile, Provider, ProviderHealth} from "@/types";
 
@@ -200,6 +206,11 @@ export function ProviderCard({
       (bound === undefined || providerProtocol(provider.type) === providerProtocol(bound.type)),
   );
 
+  // Codex reads nothing but the Responses API, which Gateway serves by
+  // translating it: a provider stopping at chat completions is out of its reach
+  // directly, so the choice is not offered rather than failing on the write.
+  const gatewayOnly = agentNeedsResponsesApi(agent.agentId) && !servesResponsesApi(bound);
+
   const toggleFallback = (id: string) => {
     onRouting({
       fallbacks: fallbacks.includes(id)
@@ -273,7 +284,7 @@ export function ProviderCard({
               <Switch
                 className="mt-0.5"
                 checked={mode === gatewayMode}
-                disabled={busy}
+                disabled={busy || gatewayOnly}
                 onCheckedChange={checked =>
                   onRouting({mode: checked ? gatewayMode : directMode})
                 }
@@ -281,9 +292,11 @@ export function ProviderCard({
               <span>
                 {i18next.t("agent:Route through Gateway")}
                 <span className="block text-muted-foreground">
-                  {mode === gatewayMode
-                    ? i18next.t("agent:Gateway mode hint")
-                    : i18next.t("agent:Direct mode hint")}
+                  {gatewayOnly
+                    ? i18next.t("agent:Gateway only hint")
+                    : mode === gatewayMode
+                      ? i18next.t("agent:Gateway mode hint")
+                      : i18next.t("agent:Direct mode hint")}
                 </span>
               </span>
             </label>
diff --git a/web/src/lib/agents.ts b/web/src/lib/agents.ts
index 15acbb2..0a2043d 100644
--- a/web/src/lib/agents.ts
+++ b/web/src/lib/agents.ts
@@ -65,6 +65,15 @@ export function agentSetupNoteKey(agentId: string) {
   }
 }
 
+/**
+ * Mirrors the check in agentprovider's Codex writer: Codex speaks only the
+ * OpenAI Responses API, so it reaches a chat completions provider through
+ * Gateway, which translates, or not at all.
+ */
+export function agentNeedsResponsesApi(agentId: string) {
+  return agentId.startsWith("codex");
+}
+
 /** The detail page route for one installation, disambiguated by its path. */
 export function agentDetailPath(agent: Agent) {
   return `/agents/${encodeURIComponent(agent.agentId)}?path=${encodeURIComponent(agent.path)}`;
diff --git a/web/src/lib/providers.ts b/web/src/lib/providers.ts
index 2ab910e..a679c40 100644
--- a/web/src/lib/providers.ts
+++ b/web/src/lib/providers.ts
@@ -24,6 +24,11 @@ export function providerProtocol(type: string) {
 export const authProvider = "provider";
 export const authClient = "client";
 
+/** Mirrors object.ServesResponsesApi: only OpenAI itself serves that API. */
+export function servesResponsesApi(provider: {type?: string} | undefined) {
+  return provider?.type === "openai";
+}
+
 /** Mirrors object.UsesClientAuth: whose credentials reach the upstream. */
 export function usesClientAuth(provider: {authMode?: string} | undefined) {
   return provider?.authMode === authClient;
diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json
index 360cf96..d009812 100644
--- a/web/src/locales/en/data.json
+++ b/web/src/locales/en/data.json
@@ -40,7 +40,7 @@
     "Bound provider cooling down": "The bound provider is out of rotation, requests go to the fallbacks",
     "Claude Code config hint": "The same variables can live in the \"env\" block of ~/.claude/settings.json, so every session picks them up without exporting anything.",
     "Client auth token hint": "This provider forwards the agent's own credentials, so no token is set: the agent keeps the sign-in it already has.",
-    "Codex CLI config hint": "The base URL can also be a model provider in ~/.codex/config.toml, selected with model_provider.",
+    "Codex CLI config hint": "The base URL can also be a model provider in ~/.codex/config.toml, selected with model_provider. Its wire_api has to be \"responses\", the only wire format Codex still speaks.",
     "Configuration preview": "Configuration preview",
     "Configuration restored": "Configuration restored",
     "Configuration written": "Configuration written",
@@ -68,6 +68,7 @@
     "From the transcript": "From the transcript",
     "Gateway": "Gateway",
     "Gateway mode hint": "The agent is pointed at the local proxy, so switching to another provider takes effect on the next request without restarting the agent.",
+    "Gateway only hint": "Codex speaks only the OpenAI Responses API. Gateway serves it by translating to the chat completions this provider answers, so Codex cannot be pointed at it directly.",
     "Image": "Image",
     "Install Method": "Install Method",
     "Install an AI agent on this machine, then scan again": "Install an AI agent on this machine, then scan again",
diff --git a/web/src/locales/zh/data.json b/web/src/locales/zh/data.json
index 88f9a94..1723f87 100644
--- a/web/src/locales/zh/data.json
+++ b/web/src/locales/zh/data.json
@@ -40,7 +40,7 @@
     "Bound provider cooling down": "绑定的供应商已暂时移出轮转,请求将走备用供应商",
     "Claude Code config hint": "这两个变量也可以写进 ~/.claude/settings.json 的 env 段,这样不用每次 export,所有会话都会生效。",
     "Client auth token hint": "该供应商转发 Agent 自己的凭据,所以不设置 token,Agent 继续用它已有的登录。",
-    "Codex CLI config hint": "base URL 也可以写成 ~/.codex/config.toml 里的一个 model provider,再用 model_provider 选中它。",
+    "Codex CLI config hint": "base URL 也可以写成 ~/.codex/config.toml 里的一个 model provider,再用 model_provider 选中它。它的 wire_api 必须是 \"responses\",这是 Codex 现在唯一还支持的线格式。",
     "Configuration preview": "配置预览",
     "Configuration restored": "配置已还原",
     "Configuration written": "配置已写入",
@@ -68,6 +68,7 @@
     "From the transcript": "来自会话记录",
     "Gateway": "网关",
     "Gateway mode hint": "把 Agent 指向本地代理,切换供应商在下一次请求即生效,无需重启 Agent。",
+    "Gateway only hint": "Codex 只会说 OpenAI Responses API。Gateway 会把它翻译成该供应商应答的 chat completions,所以 Codex 无法直连这个供应商。",
     "Image": "图片",
     "Install Method": "安装方式",
     "Install an AI agent on this machine, then scan again": "在本机安装一个 AI 智能体后,再扫描一次",


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@casbin.apache.org
For additional commands, e-mail: commits-help@casbin.apache.org