mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-08-02 18:41:35 +08:00
revert: restore full config overwrite + Common Config Snippet (revert 992dda5c)
Revert the partial key-field merging refactoring introduced in992dda5c, along with two dependent commits (24fa8a18,87604b18) that referenced the now-removed ClaudeQuickToggles component. The whitelist-based partial merge approach had critical issues: - Non-whitelisted custom fields were lost during provider switching - Backfill permanently stripped non-key fields from the database - Whitelist required constant maintenance to track upstream changes This restores the proven "full config overwrite + Common Config Snippet" architecture where each provider stores its complete configuration and shared settings are managed via a separate snippet mechanism. Reverted commits: -24fa8a18: context-aware JSON editor hint + hide quick toggles -87604b18: hide ClaudeQuickToggles when creating -992dda5c: partial key-field merging refactoring Restored: - Full config snapshot write (write_live_snapshot) for Claude/Codex/Gemini - Full config backfill (settings_config = live_config) - Common Config Snippet UI and backend commands - 6 frontend components/hooks for common config editing - configApi barrel export and DB snippet methods Removed: - ClaudeQuickToggles component - write_live_partial / backfill_key_fields / patch_claude_live - All KEY_FIELDS constants
This commit is contained in:
@@ -14,7 +14,6 @@ import type {
|
||||
ProviderTestConfig,
|
||||
ProviderProxyConfig,
|
||||
ClaudeApiFormat,
|
||||
ClaudeApiKeyField,
|
||||
} from "@/types";
|
||||
import {
|
||||
providerPresets,
|
||||
@@ -47,9 +46,9 @@ import {
|
||||
import { mergeProviderMeta } from "@/utils/providerMetaUtils";
|
||||
import { getCodexCustomTemplate } from "@/config/codexTemplates";
|
||||
import CodexConfigEditor from "./CodexConfigEditor";
|
||||
import { CommonConfigEditor } from "./CommonConfigEditor";
|
||||
import GeminiConfigEditor from "./GeminiConfigEditor";
|
||||
import JsonEditor from "@/components/JsonEditor";
|
||||
import { ClaudeQuickToggles, jsonMergePatch } from "./ClaudeQuickToggles";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { ProviderPresetSelector } from "./ProviderPresetSelector";
|
||||
import { BasicFormFields } from "./BasicFormFields";
|
||||
@@ -70,9 +69,12 @@ import {
|
||||
useCodexConfigState,
|
||||
useApiKeyLink,
|
||||
useTemplateValues,
|
||||
useCommonConfigSnippet,
|
||||
useCodexCommonConfig,
|
||||
useSpeedTestEndpoints,
|
||||
useCodexTomlValidation,
|
||||
useGeminiConfigState,
|
||||
useGeminiCommonConfig,
|
||||
useOmoModelSource,
|
||||
useOpencodeFormState,
|
||||
useOmoDraftState,
|
||||
@@ -116,7 +118,6 @@ interface ProviderFormProps {
|
||||
iconColor?: string;
|
||||
};
|
||||
showButtons?: boolean;
|
||||
isCurrent?: boolean;
|
||||
}
|
||||
|
||||
export function ProviderForm({
|
||||
@@ -129,7 +130,6 @@ export function ProviderForm({
|
||||
onManageUniversalProviders,
|
||||
initialData,
|
||||
showButtons = true,
|
||||
isCurrent = false,
|
||||
}: ProviderFormProps) {
|
||||
const { t } = useTranslation();
|
||||
const isEditMode = Boolean(initialData);
|
||||
@@ -237,55 +237,6 @@ export function ProviderForm({
|
||||
mode: "onSubmit",
|
||||
});
|
||||
|
||||
const [localApiFormat, setLocalApiFormat] = useState<ClaudeApiFormat>(() => {
|
||||
if (appId !== "claude") return "anthropic";
|
||||
return initialData?.meta?.apiFormat ?? "anthropic";
|
||||
});
|
||||
|
||||
const handleApiFormatChange = useCallback((format: ClaudeApiFormat) => {
|
||||
setLocalApiFormat(format);
|
||||
}, []);
|
||||
|
||||
const [localApiKeyField, setLocalApiKeyField] = useState<ClaudeApiKeyField>(
|
||||
() => {
|
||||
if (appId !== "claude") return "ANTHROPIC_AUTH_TOKEN";
|
||||
if (initialData?.meta?.apiKeyField) return initialData.meta.apiKeyField;
|
||||
try {
|
||||
const config = initialData?.settingsConfig;
|
||||
if (
|
||||
config?.env &&
|
||||
(config.env as Record<string, unknown>).ANTHROPIC_API_KEY !==
|
||||
undefined
|
||||
)
|
||||
return "ANTHROPIC_API_KEY";
|
||||
} catch {}
|
||||
return "ANTHROPIC_AUTH_TOKEN";
|
||||
},
|
||||
);
|
||||
|
||||
const handleApiKeyFieldChange = useCallback(
|
||||
(field: ClaudeApiKeyField) => {
|
||||
setLocalApiKeyField(field);
|
||||
try {
|
||||
const config = JSON.parse(form.getValues("settingsConfig") || "{}") as {
|
||||
env?: Record<string, unknown>;
|
||||
};
|
||||
const env = (config.env ?? {}) as Record<string, unknown>;
|
||||
const oldField =
|
||||
field === "ANTHROPIC_API_KEY"
|
||||
? "ANTHROPIC_AUTH_TOKEN"
|
||||
: "ANTHROPIC_API_KEY";
|
||||
if (oldField in env) {
|
||||
env[field] = env[oldField];
|
||||
delete env[oldField];
|
||||
config.env = env;
|
||||
form.setValue("settingsConfig", JSON.stringify(config, null, 2));
|
||||
}
|
||||
} catch {}
|
||||
},
|
||||
[form],
|
||||
);
|
||||
|
||||
const {
|
||||
apiKey,
|
||||
handleApiKeyChange,
|
||||
@@ -296,7 +247,6 @@ export function ProviderForm({
|
||||
selectedPresetId,
|
||||
category,
|
||||
appType: appId,
|
||||
apiKeyField: appId === "claude" ? localApiKeyField : undefined,
|
||||
});
|
||||
|
||||
const { baseUrl, handleClaudeBaseUrlChange } = useBaseUrlState({
|
||||
@@ -320,6 +270,15 @@ 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 handleApiFormatChange = useCallback((format: ClaudeApiFormat) => {
|
||||
setLocalApiFormat(format);
|
||||
}, []);
|
||||
|
||||
const {
|
||||
codexAuth,
|
||||
codexConfig,
|
||||
@@ -417,6 +376,37 @@ export function ProviderForm({
|
||||
onConfigChange: (config) => form.setValue("settingsConfig", config),
|
||||
});
|
||||
|
||||
const {
|
||||
useCommonConfig,
|
||||
commonConfigSnippet,
|
||||
commonConfigError,
|
||||
handleCommonConfigToggle,
|
||||
handleCommonConfigSnippetChange,
|
||||
isExtracting: isClaudeExtracting,
|
||||
handleExtract: handleClaudeExtract,
|
||||
} = useCommonConfigSnippet({
|
||||
settingsConfig: form.getValues("settingsConfig"),
|
||||
onConfigChange: (config) => form.setValue("settingsConfig", config),
|
||||
initialData: appId === "claude" ? initialData : undefined,
|
||||
selectedPresetId: selectedPresetId ?? undefined,
|
||||
enabled: appId === "claude",
|
||||
});
|
||||
|
||||
const {
|
||||
useCommonConfig: useCodexCommonConfigFlag,
|
||||
commonConfigSnippet: codexCommonConfigSnippet,
|
||||
commonConfigError: codexCommonConfigError,
|
||||
handleCommonConfigToggle: handleCodexCommonConfigToggle,
|
||||
handleCommonConfigSnippetChange: handleCodexCommonConfigSnippetChange,
|
||||
isExtracting: isCodexExtracting,
|
||||
handleExtract: handleCodexExtract,
|
||||
} = useCodexCommonConfig({
|
||||
codexConfig,
|
||||
onConfigChange: handleCodexConfigChange,
|
||||
initialData: appId === "codex" ? initialData : undefined,
|
||||
selectedPresetId: selectedPresetId ?? undefined,
|
||||
});
|
||||
|
||||
const {
|
||||
geminiEnv,
|
||||
geminiConfig,
|
||||
@@ -432,6 +422,7 @@ export function ProviderForm({
|
||||
handleGeminiConfigChange,
|
||||
resetGeminiConfig,
|
||||
envStringToObj,
|
||||
envObjToString,
|
||||
} = useGeminiConfigState({
|
||||
initialData: appId === "gemini" ? initialData : undefined,
|
||||
});
|
||||
@@ -482,6 +473,23 @@ export function ProviderForm({
|
||||
[originalHandleGeminiModelChange, updateGeminiEnvField],
|
||||
);
|
||||
|
||||
const {
|
||||
useCommonConfig: useGeminiCommonConfigFlag,
|
||||
commonConfigSnippet: geminiCommonConfigSnippet,
|
||||
commonConfigError: geminiCommonConfigError,
|
||||
handleCommonConfigToggle: handleGeminiCommonConfigToggle,
|
||||
handleCommonConfigSnippetChange: handleGeminiCommonConfigSnippetChange,
|
||||
isExtracting: isGeminiExtracting,
|
||||
handleExtract: handleGeminiExtract,
|
||||
} = useGeminiCommonConfig({
|
||||
envValue: geminiEnv,
|
||||
onEnvChange: handleGeminiEnvChange,
|
||||
envStringToObj,
|
||||
envObjToString,
|
||||
initialData: appId === "gemini" ? initialData : undefined,
|
||||
selectedPresetId: selectedPresetId ?? undefined,
|
||||
});
|
||||
|
||||
// ── Extracted hooks: OpenCode / OMO / OpenClaw ─────────────────────
|
||||
|
||||
const {
|
||||
@@ -520,6 +528,8 @@ export function ProviderForm({
|
||||
getSettingsConfig: () => form.getValues("settingsConfig"),
|
||||
});
|
||||
|
||||
const [isCommonConfigModalOpen, setIsCommonConfigModalOpen] = useState(false);
|
||||
|
||||
const handleSubmit = (values: ProviderFormData) => {
|
||||
if (appId === "claude" && templateValueEntries.length > 0) {
|
||||
const validation = validateTemplateValues();
|
||||
@@ -813,10 +823,6 @@ export function ProviderForm({
|
||||
appId === "claude" && category !== "official"
|
||||
? localApiFormat
|
||||
: undefined,
|
||||
apiKeyField:
|
||||
appId === "claude" && category !== "official"
|
||||
? localApiKeyField
|
||||
: undefined,
|
||||
};
|
||||
|
||||
onSubmit(payload);
|
||||
@@ -1055,12 +1061,6 @@ export function ProviderForm({
|
||||
setLocalApiFormat("anthropic");
|
||||
}
|
||||
|
||||
if (preset.apiKeyField) {
|
||||
setLocalApiKeyField(preset.apiKeyField);
|
||||
} else {
|
||||
setLocalApiKeyField("ANTHROPIC_AUTH_TOKEN");
|
||||
}
|
||||
|
||||
form.reset({
|
||||
name: preset.name,
|
||||
websiteUrl: preset.websiteUrl ?? "",
|
||||
@@ -1266,8 +1266,6 @@ export function ProviderForm({
|
||||
speedTestEndpoints={speedTestEndpoints}
|
||||
apiFormat={localApiFormat}
|
||||
onApiFormatChange={handleApiFormatChange}
|
||||
apiKeyField={localApiKeyField}
|
||||
onApiKeyFieldChange={handleApiKeyFieldChange}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1394,8 +1392,15 @@ export function ProviderForm({
|
||||
configValue={codexConfig}
|
||||
onAuthChange={setCodexAuth}
|
||||
onConfigChange={handleCodexConfigChange}
|
||||
useCommonConfig={useCodexCommonConfigFlag}
|
||||
onCommonConfigToggle={handleCodexCommonConfigToggle}
|
||||
commonConfigSnippet={codexCommonConfigSnippet}
|
||||
onCommonConfigSnippetChange={handleCodexCommonConfigSnippetChange}
|
||||
commonConfigError={codexCommonConfigError}
|
||||
authError={codexAuthError}
|
||||
configError={codexConfigError}
|
||||
onExtract={handleCodexExtract}
|
||||
isExtracting={isCodexExtracting}
|
||||
/>
|
||||
{settingsConfigErrorField}
|
||||
</>
|
||||
@@ -1406,8 +1411,17 @@ export function ProviderForm({
|
||||
configValue={geminiConfig}
|
||||
onEnvChange={handleGeminiEnvChange}
|
||||
onConfigChange={handleGeminiConfigChange}
|
||||
useCommonConfig={useGeminiCommonConfigFlag}
|
||||
onCommonConfigToggle={handleGeminiCommonConfigToggle}
|
||||
commonConfigSnippet={geminiCommonConfigSnippet}
|
||||
onCommonConfigSnippetChange={
|
||||
handleGeminiCommonConfigSnippetChange
|
||||
}
|
||||
commonConfigError={geminiCommonConfigError}
|
||||
envError={envError}
|
||||
configError={geminiConfigError}
|
||||
onExtract={handleGeminiExtract}
|
||||
isExtracting={isGeminiExtracting}
|
||||
/>
|
||||
{settingsConfigErrorField}
|
||||
</>
|
||||
@@ -1477,48 +1491,20 @@ export function ProviderForm({
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="settingsConfig">
|
||||
{t("claudeConfig.configLabel")}
|
||||
</Label>
|
||||
{isEditMode && isCurrent && (
|
||||
<ClaudeQuickToggles
|
||||
onPatchApplied={(patch) => {
|
||||
try {
|
||||
const cfg = JSON.parse(
|
||||
form.getValues("settingsConfig") || "{}",
|
||||
);
|
||||
jsonMergePatch(cfg, patch);
|
||||
form.setValue(
|
||||
"settingsConfig",
|
||||
JSON.stringify(cfg, null, 2),
|
||||
);
|
||||
} catch {
|
||||
// invalid JSON in editor — skip mirror
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<JsonEditor
|
||||
value={form.watch("settingsConfig")}
|
||||
onChange={(value) => form.setValue("settingsConfig", value)}
|
||||
placeholder={`{
|
||||
"env": {
|
||||
"ANTHROPIC_AUTH_TOKEN": "your-api-key-here"
|
||||
}
|
||||
}`}
|
||||
rows={14}
|
||||
showValidation={true}
|
||||
language="json"
|
||||
/>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t(
|
||||
isCurrent
|
||||
? "claudeConfig.fullSettingsHint"
|
||||
: "claudeConfig.fragmentSettingsHint",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<CommonConfigEditor
|
||||
value={form.getValues("settingsConfig")}
|
||||
onChange={(value) => form.setValue("settingsConfig", value)}
|
||||
useCommonConfig={useCommonConfig}
|
||||
onCommonConfigToggle={handleCommonConfigToggle}
|
||||
commonConfigSnippet={commonConfigSnippet}
|
||||
onCommonConfigSnippetChange={handleCommonConfigSnippetChange}
|
||||
commonConfigError={commonConfigError}
|
||||
onEditClick={() => setIsCommonConfigModalOpen(true)}
|
||||
isModalOpen={isCommonConfigModalOpen}
|
||||
onModalClose={() => setIsCommonConfigModalOpen(false)}
|
||||
onExtract={handleClaudeExtract}
|
||||
isExtracting={isClaudeExtracting}
|
||||
/>
|
||||
{settingsConfigErrorField}
|
||||
</>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user