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