feat: sync current providers to live files after config import
Core Improvements: - Add sync_current_providers_live command to synchronize in-memory provider settings to corresponding live files (~/.claude/settings.json or ~/.codex/auth.json) - Introduce partial-success state to distinguish between 'import succeeded but sync failed' scenario, providing clear user feedback - Remove unused skip_live_backfill parameter from switch_provider command - Separate responsibilities: backend handles import/backup, frontend handles sync/error presentation Technical Details: - Codex: sync auth.json + config.toml with MCP configuration - Claude: sync settings.json - Bidirectional sync: read back after write to update in-memory settings_config - Full i18n support (English and Chinese) - Graceful handling when no current provider is active Affected Files: - Backend: import_export.rs, commands.rs, lib.rs - Frontend: useImportExport.ts, ImportExportSection.tsx, settings.ts - i18n: en.json, zh.json This ensures SSOT (Single Source of Truth) consistency between config.json and live configuration files after import operations.
This commit is contained in:
@@ -3,7 +3,12 @@ import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import { settingsApi } from "@/lib/api";
|
||||
|
||||
export type ImportStatus = "idle" | "importing" | "success" | "error";
|
||||
export type ImportStatus =
|
||||
| "idle"
|
||||
| "importing"
|
||||
| "success"
|
||||
| "partial-success"
|
||||
| "error";
|
||||
|
||||
export interface UseImportExportOptions {
|
||||
onImportSuccess?: () => void | Promise<void>;
|
||||
@@ -86,8 +91,22 @@ export function useImportExport(
|
||||
|
||||
try {
|
||||
const result = await settingsApi.importConfigFromFile(selectedFile);
|
||||
if (result.success) {
|
||||
setBackupId(result.backupId ?? null);
|
||||
if (!result.success) {
|
||||
setStatus("error");
|
||||
const message =
|
||||
result.message ||
|
||||
t("settings.configCorrupted", {
|
||||
defaultValue: "配置文件已损坏或格式不正确",
|
||||
});
|
||||
setErrorMessage(message);
|
||||
toast.error(message);
|
||||
return;
|
||||
}
|
||||
|
||||
setBackupId(result.backupId ?? null);
|
||||
|
||||
try {
|
||||
await settingsApi.syncCurrentProvidersLive();
|
||||
setStatus("success");
|
||||
toast.success(
|
||||
t("settings.importSuccess", {
|
||||
@@ -98,15 +117,15 @@ export function useImportExport(
|
||||
successTimerRef.current = window.setTimeout(() => {
|
||||
void onImportSuccess?.();
|
||||
}, 1500);
|
||||
} else {
|
||||
setStatus("error");
|
||||
const message =
|
||||
result.message ||
|
||||
t("settings.configCorrupted", {
|
||||
defaultValue: "配置文件已损坏或格式不正确",
|
||||
});
|
||||
setErrorMessage(message);
|
||||
toast.error(message);
|
||||
} catch (error) {
|
||||
console.error("[useImportExport] Failed to sync live config", error);
|
||||
setStatus("partial-success");
|
||||
toast.warning(
|
||||
t("settings.importPartialSuccess", {
|
||||
defaultValue:
|
||||
"配置已导入,但同步到当前供应商失败。请手动重新选择一次供应商。",
|
||||
}),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[useImportExport] Failed to import config", error);
|
||||
|
||||
Reference in New Issue
Block a user