fix(proxy): unify preview/runtime URL rules and proxy checks

- align Codex preview URL building with runtime /v1 normalization

- align Claude full-url detection with runtime adapter patterns

- reflect Claude ?beta=true in proxy preview and avoid query-only mismatch false positives

- enforce openai_chat proxy requirement even when baseUrl is missing

- wire Codex api format selector through ProviderForm and persist meta/config

- fix EndpointField stale async preview race on clear

- add pending feedback for ProxyToggle pre-disable checks

- deduplicate provider baseUrl extraction into a shared util
This commit is contained in:
YoVinchen
2026-02-11 23:37:38 +08:00
parent fd2793abc4
commit 246ec65789
8 changed files with 297 additions and 164 deletions
+57 -17
View File
@@ -35,7 +35,11 @@ import {
} from "@/config/opencodeProviderPresets";
import { OpenCodeFormFields } from "./OpenCodeFormFields";
import type { UniversalProviderPreset } from "@/config/universalProviderPresets";
import { applyTemplateValues } from "@/utils/providerConfigUtils";
import {
applyTemplateValues,
extractCodexWireApi,
setCodexWireApi,
} from "@/utils/providerConfigUtils";
import { mergeProviderMeta } from "@/utils/providerMetaUtils";
import { getCodexCustomTemplate } from "@/config/codexTemplates";
import CodexConfigEditor from "./CodexConfigEditor";
@@ -46,7 +50,7 @@ import { Label } from "@/components/ui/label";
import { ProviderPresetSelector } from "./ProviderPresetSelector";
import { BasicFormFields } from "./BasicFormFields";
import { ClaudeFormFields } from "./ClaudeFormFields";
import { CodexFormFields } from "./CodexFormFields";
import { CodexFormFields, type CodexApiFormat } from "./CodexFormFields";
import { GeminiFormFields } from "./GeminiFormFields";
import { OmoFormFields } from "./OmoFormFields";
import { type OmoGlobalConfigFieldsRef } from "./OmoGlobalConfigFields";
@@ -357,14 +361,26 @@ export function ProviderForm({
onConfigChange: (config) => form.setValue("settingsConfig", config),
});
const [localApiFormat, setLocalApiFormat] = useState<ClaudeApiFormat>(() => {
if (appId !== "claude") return "anthropic";
return initialData?.meta?.apiFormat ?? "anthropic";
});
const [localClaudeApiFormat, setLocalClaudeApiFormat] =
useState<ClaudeApiFormat>(() => {
if (appId !== "claude") return "anthropic";
return initialData?.meta?.apiFormat === "openai_chat"
? "openai_chat"
: "anthropic";
});
const handleApiFormatChange = useCallback((format: ClaudeApiFormat) => {
setLocalApiFormat(format);
}, []);
const [localCodexApiFormat, setLocalCodexApiFormat] =
useState<CodexApiFormat>(() => {
if (appId !== "codex") return "responses";
if (initialData?.meta?.apiFormat === "chat") return "chat";
if (initialData?.meta?.apiFormat === "responses") return "responses";
const initialConfig = initialData?.settingsConfig?.config;
if (typeof initialConfig === "string") {
return extractCodexWireApi(initialConfig) ?? "responses";
}
return "responses";
});
const {
codexAuth,
@@ -374,6 +390,7 @@ export function ProviderForm({
codexModelName,
codexAuthError,
setCodexAuth,
setCodexConfig,
handleCodexApiKeyChange,
handleCodexBaseUrlChange,
handleCodexModelNameChange,
@@ -392,6 +409,18 @@ export function ProviderForm({
[originalHandleCodexConfigChange, debouncedValidate],
);
const handleClaudeApiFormatChange = useCallback((format: ClaudeApiFormat) => {
setLocalClaudeApiFormat(format);
}, []);
const handleCodexApiFormatChange = useCallback(
(format: CodexApiFormat) => {
setLocalCodexApiFormat(format);
setCodexConfig((prev) => setCodexWireApi(prev, format));
},
[setCodexConfig],
);
useEffect(() => {
if (appId === "codex" && !initialData && selectedPresetId === "custom") {
const template = getCodexCustomTemplate();
@@ -1166,6 +1195,13 @@ export function ProviderForm({
}
}
const providerApiFormat =
appId === "claude" && category !== "official"
? localClaudeApiFormat
: appId === "codex" && category !== "official"
? localCodexApiFormat
: undefined;
const baseMeta: ProviderMeta | undefined =
payload.meta ?? (initialData?.meta ? { ...initialData.meta } : undefined);
payload.meta = {
@@ -1180,10 +1216,7 @@ export function ProviderForm({
pricingConfig.enabled && pricingConfig.pricingModelSource !== "inherit"
? pricingConfig.pricingModelSource
: undefined,
apiFormat:
appId === "claude" && category !== "official"
? localApiFormat
: undefined,
apiFormat: providerApiFormat,
};
onSubmit(payload);
@@ -1277,6 +1310,9 @@ export function ProviderForm({
if (appId === "codex") {
const template = getCodexCustomTemplate();
setLocalCodexApiFormat(
extractCodexWireApi(template.config) ?? "responses",
);
resetCodexConfig(template.auth, template.config);
}
if (appId === "gemini") {
@@ -1311,6 +1347,7 @@ export function ProviderForm({
const auth = preset.auth ?? {};
const config = preset.config ?? "";
setLocalCodexApiFormat(extractCodexWireApi(config) ?? "responses");
resetCodexConfig(auth, config);
form.reset({
@@ -1381,9 +1418,9 @@ export function ProviderForm({
);
if (preset.apiFormat) {
setLocalApiFormat(preset.apiFormat);
setLocalClaudeApiFormat(preset.apiFormat);
} else {
setLocalApiFormat("anthropic");
setLocalClaudeApiFormat("anthropic");
}
form.reset({
@@ -1518,8 +1555,8 @@ export function ProviderForm({
defaultOpusModel={defaultOpusModel}
onModelChange={handleModelChange}
speedTestEndpoints={speedTestEndpoints}
apiFormat={localApiFormat}
onApiFormatChange={handleApiFormatChange}
apiFormat={localClaudeApiFormat}
onApiFormatChange={handleClaudeApiFormatChange}
/>
)}
@@ -1547,6 +1584,9 @@ export function ProviderForm({
modelName={codexModelName}
onModelNameChange={handleCodexModelNameChange}
speedTestEndpoints={speedTestEndpoints}
apiFormat={localCodexApiFormat}
onApiFormatChange={handleCodexApiFormatChange}
shouldShowApiFormatSelector={category !== "official"}
/>
)}
@@ -49,6 +49,8 @@ export function EndpointField({
// 调用后端 API 获取 URL 预览
useEffect(() => {
if (!value || !appType || !showUrlPreview) {
// 标记当前所有已发出的请求为过期,避免旧请求回写
lastRequestIdRef.current += 1;
setUrlPreview(null);
return;
}
@@ -114,7 +116,7 @@ export function EndpointField({
</p>
<p className="text-xs text-muted-foreground/70 mt-0.5 pl-4">
{t("providerForm.directRequestUrlDesc", {
defaultValue: "CLI 硬拼接默认后缀后的实际请求地址",
defaultValue: "CLI 直连模式下的实际请求地址",
})}
</p>
</div>