diff --git a/src/app/components/ImageModelsEditor.tsx b/src/app/components/ImageModelsEditor.tsx
index 4c48f9e..37c7535 100644
--- a/src/app/components/ImageModelsEditor.tsx
+++ b/src/app/components/ImageModelsEditor.tsx
@@ -5,6 +5,8 @@ import { useTranslations } from "next-intl";
import { Eye, EyeOff } from "lucide-react";
import { toast } from "sonner";
import { errorToast } from "@/lib/errorReporter";
+import { ConfigImportDialog } from "@/app/components/ConfigImportDialog";
+import { downloadTextFile, exportFilename } from "@/lib/configTransfer";
import { Button } from "@/components/ui/button";
import {
getImageGeneration,
@@ -372,6 +374,28 @@ export function ImageModelsEditor() {
const [forbidden, setForbidden] = useState(false);
const [saving, setSaving] = useState(false);
const t = useTranslations("imageModels");
+ const tc = useTranslations("configTransfer");
+ const [importOpen, setImportOpen] = useState(false);
+ const [exporting, setExporting] = useState(false);
+
+ const runExport = useCallback(async () => {
+ setExporting(true);
+ try {
+ const response = await fetch("/api/image-generation/export", {
+ cache: "no-store",
+ });
+ if (!response.ok) {
+ errorToast(
+ "models.image-export",
+ tc("exportFailed", { status: String(response.status) })
+ );
+ return;
+ }
+ downloadTextFile(exportFilename("image-generation"), await response.text());
+ } finally {
+ setExporting(false);
+ }
+ }, [tc]);
const load = useCallback(async () => {
setLoadError(null);
@@ -497,28 +521,49 @@ export function ImageModelsEditor() {
{t("modelsHeading")}
-
+
+
+
+
+
{draft.models.length === 0 && (
{t("empty")}
@@ -570,6 +615,12 @@ export function ImageModelsEditor() {
{t("apiKeyWriteOnlyNote")}
+
);
}
diff --git a/src/app/components/RegistryEditor.tsx b/src/app/components/RegistryEditor.tsx
index 0198e51..df84724 100644
--- a/src/app/components/RegistryEditor.tsx
+++ b/src/app/components/RegistryEditor.tsx
@@ -5,6 +5,8 @@ import { useTranslations } from "next-intl";
import { ChevronDown, ChevronRight, Eye, EyeOff } from "lucide-react";
import { toast } from "sonner";
import { errorToast } from "@/lib/errorReporter";
+import { ConfigImportDialog } from "@/app/components/ConfigImportDialog";
+import { downloadTextFile, exportFilename } from "@/lib/configTransfer";
import { Button } from "@/components/ui/button";
import { invalidateAvailableModels } from "@/app/hooks/useAvailableModels";
import type {
@@ -934,6 +936,9 @@ function ProviderEditor({
* controls from `adapter_specs` and surfaces 422 detail paths verbatim. */
export function RegistryEditor() {
const t = useTranslations("modelConfig");
+ const tc = useTranslations("configTransfer");
+ const [importOpen, setImportOpen] = useState(false);
+ const [exporting, setExporting] = useState(false);
const [data, setData] = useState(null);
const [draft, setDraft] = useState(null);
const [credentialWrites, setCredentialWrites] = useState