From ecd281611e1f50ecb3a88bbf2158bd4dbd3500b6 Mon Sep 17 00:00:00 2001 From: Kevin Ho Date: Sun, 24 May 2026 22:21:28 -0700 Subject: [PATCH 1/2] feat: native AI-assisted Magic Rewrite for character, persona, and lorebook fields (#1183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add POST /api/magic-rewrite/generate endpoint using configured LLM connections - Connection resolution: rewrite-specific → default chat → agent default - New 'Default for Rewrite' per-connection toggle in Connection Settings - MagicRewritePanel component with instructions, context selectors, diff preview - Integrated into LorebookFormFields and shared ExpandedTextarea component - Covers character editor, persona editor, chat settings, and lorebook entries - DB migration adds default_for_rewrite column with mutual-exclusion enforcement --- .../connections/ConnectionEditor.tsx | 31 +++ .../lorebooks/LorebookFormFields.tsx | 98 +++++-- .../src/components/ui/ExpandedTextarea.tsx | 97 +++++-- .../src/components/ui/MagicRewritePanel.tsx | 243 ++++++++++++++++++ packages/server/src/db/migrate.ts | 5 + packages/server/src/db/schema/connections.ts | 2 + packages/server/src/routes/index.ts | 2 + .../server/src/routes/magic-rewrite.routes.ts | 97 +++++++ .../services/storage/connections.storage.ts | 35 +++ .../shared/src/schemas/connection.schema.ts | 1 + packages/shared/src/types/connection.ts | 2 + 11 files changed, 574 insertions(+), 39 deletions(-) create mode 100644 packages/client/src/components/ui/MagicRewritePanel.tsx create mode 100644 packages/server/src/routes/magic-rewrite.routes.ts diff --git a/packages/client/src/components/connections/ConnectionEditor.tsx b/packages/client/src/components/connections/ConnectionEditor.tsx index 737f3d40c..55e26704f 100644 --- a/packages/client/src/components/connections/ConnectionEditor.tsx +++ b/packages/client/src/components/connections/ConnectionEditor.tsx @@ -43,6 +43,7 @@ import { ImageIcon, RotateCcw, SlidersHorizontal, + Sparkles, } from "lucide-react"; import { cn } from "../../lib/utils"; import { showConfirmDialog } from "../../lib/app-dialogs"; @@ -149,6 +150,7 @@ export function ConnectionEditor() { const [localEnableCaching, setLocalEnableCaching] = useState(false); const [localCachingAtDepth, setLocalCachingAtDepth] = useState(DEFAULT_CACHING_AT_DEPTH); const [localDefaultForAgents, setLocalDefaultForAgents] = useState(false); + const [localDefaultForRewrite, setLocalDefaultForRewrite] = useState(false); const [localEmbeddingModel, setLocalEmbeddingModel] = useState(""); const [localEmbeddingBaseUrl, setLocalEmbeddingBaseUrl] = useState(""); const [localEmbeddingConnectionId, setLocalEmbeddingConnectionId] = useState(""); @@ -248,6 +250,7 @@ export function ConnectionEditor() { setLocalEnableCaching(c.enableCaching === "true" || c.enableCaching === true); setLocalCachingAtDepth(normalizeCachingAtDepth(c.cachingAtDepth)); setLocalDefaultForAgents(c.defaultForAgents === "true" || c.defaultForAgents === true); + setLocalDefaultForRewrite(c.defaultForRewrite === "true" || c.defaultForRewrite === true); setLocalEmbeddingModel((c.embeddingModel as string) ?? ""); setLocalEmbeddingBaseUrl((c.embeddingBaseUrl as string) ?? ""); setLocalEmbeddingConnectionId((c.embeddingConnectionId as string) ?? ""); @@ -412,6 +415,7 @@ export function ConnectionEditor() { enableCaching: localEnableCaching, cachingAtDepth: localCachingAtDepth, defaultForAgents: localDefaultForAgents, + defaultForRewrite: localDefaultForRewrite, embeddingModel: localEmbeddingModel, embeddingBaseUrl: localEmbeddingBaseUrl, embeddingConnectionId: localEmbeddingConnectionId || null, @@ -471,6 +475,7 @@ export function ConnectionEditor() { localEnableCaching, localCachingAtDepth, localDefaultForAgents, + localDefaultForRewrite, localEmbeddingModel, localEmbeddingBaseUrl, localEmbeddingConnectionId, @@ -1725,6 +1730,32 @@ export function ConnectionEditor() { )} + {/* ── Default for Magic Rewrite ── */} + {!isImageGenerationProvider && ( + } + help="When enabled, all Magic Rewrite text generations will use this connection. Otherwise the default chat connection will be used." + > +