diff --git a/apps/server/src/express.d.ts b/apps/server/src/express.d.ts
index f2cb77c78..781c6db55 100644
--- a/apps/server/src/express.d.ts
+++ b/apps/server/src/express.d.ts
@@ -1,14 +1,7 @@
-import { Session } from "express-session";
+import type { SessionData } from "express-session";
 
 export declare module "express-serve-static-core" {
     interface Request {
-        session: Session & {
-            loggedIn: boolean;
-            lastAuthState: {
-                totpEnabled: boolean;
-                ssoEnabled: boolean;
-            };
-        };
         headers: {
             "x-local-date"?: string;
             "x-labels"?: string;
@@ -25,3 +18,13 @@ export declare module "express-serve-static-core" {
         };
     }
 }
+
+export declare module "express-session" {
+    interface SessionData {
+        loggedIn: boolean;
+        lastAuthState: {
+            totpEnabled: boolean;
+            ssoEnabled: boolean;
+        };
+    }
+}
diff --git a/apps/server/src/routes/api/embeddings.ts b/apps/server/src/routes/api/embeddings.ts
index 012a9c82f..226231ea2 100644
--- a/apps/server/src/routes/api/embeddings.ts
+++ b/apps/server/src/routes/api/embeddings.ts
@@ -408,7 +408,7 @@ async function reprocessAllNotes(req: Request, res: Response) {
         try {
             // Wrap the operation in cls.init to ensure proper context
             cls.init(async () => {
-                await vectorStore.reprocessAllNotes();
+                await indexService.reprocessAllNotes();
                 log.info("Embedding reprocessing completed successfully");
             });
         } catch (error: any) {
@@ -782,6 +782,49 @@ async function getIndexRebuildStatus(req: Request, res: Response) {
     };
 }
 
+/**
+ * Start embedding generation when AI is enabled
+ */
+async function startEmbeddings(req: Request, res: Response) {
+    try {
+        log.info("Starting embedding generation system");
+        
+        // Initialize the index service if not already initialized
+        await indexService.initialize();
+        
+        // Start automatic indexing
+        await indexService.startEmbeddingGeneration();
+        
+        return {
+            success: true,
+            message: "Embedding generation started"
+        };
+    } catch (error: any) {
+        log.error(`Error starting embeddings: ${error.message || 'Unknown error'}`);
+        throw new Error(`Failed to start embeddings: ${error.message || 'Unknown error'}`);
+    }
+}
+
+/**
+ * Stop embedding generation when AI is disabled
+ */
+async function stopEmbeddings(req: Request, res: Response) {
+    try {
+        log.info("Stopping embedding generation system");
+        
+        // Stop automatic indexing
+        await indexService.stopEmbeddingGeneration();
+        
+        return {
+            success: true,
+            message: "Embedding generation stopped"
+        };
+    } catch (error: any) {
+        log.error(`Error stopping embeddings: ${error.message || 'Unknown error'}`);
+        throw new Error(`Failed to stop embeddings: ${error.message || 'Unknown error'}`);
+    }
+}
+
 export default {
     findSimilarNotes,
     searchByText,
@@ -794,5 +837,7 @@ export default {
     retryFailedNote,
     retryAllFailedNotes,
     rebuildIndex,
-    getIndexRebuildStatus
+    getIndexRebuildStatus,
+    startEmbeddings,
+    stopEmbeddings
 };
diff --git a/apps/server/src/routes/api/llm.ts b/apps/server/src/routes/api/llm.ts
index c21426a66..f586b85d6 100644
--- a/apps/server/src/routes/api/llm.ts
+++ b/apps/server/src/routes/api/llm.ts
@@ -825,7 +825,10 @@ async function streamMessage(req: Request, res: Response) {
             success: true,
             message: 'Streaming initiated successfully'
         });
-        log.info(`Sent immediate success response for streaming setup`);
+        
+        // Mark response as handled to prevent apiResultHandler from processing it again
+        (res as any).triliumResponseHandled = true;
+        
         
         // Create a new response object for streaming through WebSocket only
         // We won't use HTTP streaming since we've already sent the HTTP response
@@ -889,78 +892,33 @@ async function streamMessage(req: Request, res: Response) {
             thinking: showThinking ? 'Initializing streaming LLM response...' : undefined
         });
 
-        // Instead of trying to reimplement the streaming logic ourselves,
-        // delegate to restChatService but set up the correct protocol:
-        // 1. We've already sent a success response to the initial POST
-        // 2. Now we'll have restChatService process the actual streaming through WebSocket
+        // Process the LLM request using the existing service but with streaming setup
+        // Since we've already sent the initial HTTP response, we'll use the WebSocket for streaming
         try {
-            // Import the WebSocket service for sending messages
-            const wsService = (await import('../../services/ws.js')).default;
-            
-            // Create a simple pass-through response object that won't write to the HTTP response
-            // but will allow restChatService to send WebSocket messages
-            const dummyResponse = {
-                writableEnded: false,
-                // Implement methods that would normally be used by restChatService
-                write: (_chunk: string) => {
-                    // Silent no-op - we're only using WebSocket
-                    return true;
+            // Call restChatService with streaming mode enabled
+            // The important part is setting method to GET to indicate streaming mode
+            await restChatService.handleSendMessage({
+                ...req,
+                method: 'GET', // Indicate streaming mode
+                query: {
+                    ...req.query,
+                    stream: 'true' // Add the required stream parameter
                 },
-                end: (_chunk?: string) => {
-                    // Log when streaming is complete via WebSocket
-                    log.info(`[${chatNoteId}] Completed HTTP response handling during WebSocket streaming`);
-                    return dummyResponse;
+                body: {
+                    content: enhancedContent,
+                    useAdvancedContext: useAdvancedContext === true,
+                    showThinking: showThinking === true
                 },
-                setHeader: (name: string, _value: string) => {
-                    // Only log for content-type to reduce noise
-                    if (name.toLowerCase() === 'content-type') {
-                        log.info(`[${chatNoteId}] Setting up streaming for WebSocket only`);
-                    }
-                    return dummyResponse;
-                }
-            };
+                params: { chatNoteId }
+            } as unknown as Request, res);
+        } catch (streamError) {
+            log.error(`Error during WebSocket streaming: ${streamError}`);
             
-            // Process the streaming now through WebSocket only
-            try {
-                log.info(`[${chatNoteId}] Processing LLM streaming through WebSocket after successful initiation at ${new Date().toISOString()}`);
-                
-                // Call restChatService with our enhanced request and dummy response
-                // The important part is setting method to GET to indicate streaming mode
-                await restChatService.handleSendMessage({
-                    ...req,
-                    method: 'GET', // Indicate streaming mode
-                    query: {
-                        ...req.query,
-                        stream: 'true' // Add the required stream parameter
-                    },
-                    body: {
-                        content: enhancedContent,
-                        useAdvancedContext: useAdvancedContext === true,
-                        showThinking: showThinking === true
-                    },
-                    params: { chatNoteId }
-                } as unknown as Request, dummyResponse as unknown as Response);
-                
-                log.info(`[${chatNoteId}] WebSocket streaming completed at ${new Date().toISOString()}`);
-            } catch (streamError) {
-                log.error(`[${chatNoteId}] Error during WebSocket streaming: ${streamError}`);
-                
-                // Send error message through WebSocket
-                wsService.sendMessageToAllClients({
-                    type: 'llm-stream',
-                    chatNoteId: chatNoteId,
-                    error: `Error during streaming: ${streamError}`,
-                    done: true
-                });
-            }
-        } catch (error) {
-            log.error(`Error during streaming: ${error}`);
-
-            // Send error to client via WebSocket
+            // Send error message through WebSocket
             wsService.sendMessageToAllClients({
                 type: 'llm-stream',
                 chatNoteId: chatNoteId,
-                error: `Error processing message: ${error}`,
+                error: `Error during streaming: ${streamError}`,
                 done: true
             });
         }
diff --git a/apps/server/src/routes/api/openai.ts b/apps/server/src/routes/api/openai.ts
index ced03ce04..84efad2ca 100644
--- a/apps/server/src/routes/api/openai.ts
+++ b/apps/server/src/routes/api/openai.ts
@@ -66,12 +66,13 @@ async function listModels(req: Request, res: Response) {
         const apiKey = await options.getOption('openaiApiKey');
 
         if (!apiKey) {
-            throw new Error('OpenAI API key is not configured');
+            // Log warning but don't throw - some OpenAI-compatible endpoints don't require API keys
+            log.info('OpenAI API key is not configured when listing models. This may cause issues with official OpenAI endpoints.');
         }
 
-        // Initialize OpenAI client with the API key and base URL
+        // Initialize OpenAI client with the API key (or empty string) and base URL
         const openai = new OpenAI({
-            apiKey,
+            apiKey: apiKey || '', // Default to empty string if no API key
             baseURL: openaiBaseUrl
         });
 
@@ -84,9 +85,9 @@ async function listModels(req: Request, res: Response) {
         // Include all models as chat models, without filtering by specific model names
         // This allows models from providers like OpenRouter to be displayed
         const chatModels = allModels
-            .filter((model) => 
+            .filter((model) =>
                 // Exclude models that are explicitly for embeddings
-                !model.id.includes('embedding') && 
+                !model.id.includes('embedding') &&
                 !model.id.includes('embed')
             )
             .map((model) => ({
diff --git a/apps/server/src/routes/api/options.ts b/apps/server/src/routes/api/options.ts
index 42d4fb110..022b4514e 100644
--- a/apps/server/src/routes/api/options.ts
+++ b/apps/server/src/routes/api/options.ts
@@ -96,22 +96,26 @@ const ALLOWED_OPTIONS = new Set
([
     "aiEnabled",
     "aiTemperature",
     "aiSystemPrompt",
-    "aiProviderPrecedence",
+    "aiSelectedProvider",
     "openaiApiKey",
     "openaiBaseUrl",
     "openaiDefaultModel",
     "openaiEmbeddingModel",
+    "openaiEmbeddingApiKey",
+    "openaiEmbeddingBaseUrl",
     "anthropicApiKey",
     "anthropicBaseUrl",
     "anthropicDefaultModel",
     "voyageApiKey",
     "voyageEmbeddingModel",
+    "voyageEmbeddingBaseUrl",
     "ollamaBaseUrl",
     "ollamaDefaultModel",
     "ollamaEmbeddingModel",
+    "ollamaEmbeddingBaseUrl",
     "embeddingAutoUpdateEnabled",
     "embeddingDimensionStrategy",
-    "embeddingProviderPrecedence",
+    "embeddingSelectedProvider",
     "embeddingSimilarityThreshold",
     "embeddingBatchSize",
     "embeddingUpdateInterval",
diff --git a/apps/server/src/routes/login.spec.ts b/apps/server/src/routes/login.spec.ts
index 99984dbda..69e2cff6a 100644
--- a/apps/server/src/routes/login.spec.ts
+++ b/apps/server/src/routes/login.spec.ts
@@ -1,15 +1,21 @@
 import { beforeAll, describe, expect, it } from "vitest";
-import supertest from "supertest";
+import supertest, { type Response } from "supertest";
 import type { Application } from "express";
 import dayjs from "dayjs";
+import { type SQLiteSessionStore } from "./session_parser.js";
+import { SessionData } from "express-session";
 
 let app: Application;
+let sessionStore: SQLiteSessionStore;
+let CLEAN_UP_INTERVAL: number;
 
 describe("Login Route test", () => {
 
     beforeAll(async () => {
+        vi.useFakeTimers();
         const buildApp = (await import("../app.js")).default;
         app = await buildApp();
+        ({ sessionStore, CLEAN_UP_INTERVAL } = (await import("./session_parser.js")));
     });
 
     it("should return the login page, when using a GET request", async () => {
@@ -32,58 +38,171 @@ describe("Login Route test", () => {
 
     });
 
-
-    it("sets correct Expires, when 'Remember Me' is ticked", async () => {
-
+    describe("Login when 'Remember Me' is ticked", async () => {
         // TriliumNextTODO: make setting cookieMaxAge via env variable work
         // => process.env.TRILIUM_SESSION_COOKIEMAXAGE
         // the custom cookieMaxAge is currently hardocded in the test data dir's config.ini
 
-        const CUSTOM_MAX_AGE_SECONDS = 86400;
-        const expectedExpiresDate = dayjs().utc().add(CUSTOM_MAX_AGE_SECONDS, "seconds").toDate().toUTCString();
+        let res: Response;
+        let setCookieHeader: string;
+        let expectedExpiresDate: string;
 
-        const res = await supertest(app)
-            .post("/login")
-            .send({ password: "demo1234", rememberMe: 1 })
-            .expect(302)
+        beforeAll(async () => {
+            const CUSTOM_MAX_AGE_SECONDS = 86400;
 
-        const setCookieHeader = res.headers["set-cookie"][0];
+            expectedExpiresDate = dayjs().utc().add(CUSTOM_MAX_AGE_SECONDS, "seconds").toDate().toUTCString();
+            res = await supertest(app)
+                .post("/login")
+                .send({ password: "demo1234", rememberMe: 1 })
+                .expect(302);
+            setCookieHeader = res.headers["set-cookie"][0];
+        });
 
-        // match for e.g. "Expires=Wed, 07 May 2025 07:02:59 GMT;"
-        const expiresCookieRegExp = /Expires=(?[\w\s,:]+)/;
-        const expiresCookieMatch = setCookieHeader.match(expiresCookieRegExp);
-        const actualExpiresDate = new Date(expiresCookieMatch?.groups?.date || "").toUTCString()
+        it("sets correct Expires for the cookie", async () => {
+            // match for e.g. "Expires=Wed, 07 May 2025 07:02:59 GMT;"
+            const expiresCookieRegExp = /Expires=(?[\w\s,:]+)/;
+            const expiresCookieMatch = setCookieHeader.match(expiresCookieRegExp);
+            const actualExpiresDate = new Date(expiresCookieMatch?.groups?.date || "").toUTCString();
 
-        expect(actualExpiresDate).to.not.eql("Invalid Date");
+            expect(actualExpiresDate).to.not.eql("Invalid Date");
 
-        // ignore the seconds in the comparison, just to avoid flakiness in tests,
-        // if for some reason execution is slow between calculation of expected and actual
-        expect(actualExpiresDate.slice(0,23)).toBe(expectedExpiresDate.slice(0,23))
+            // ignore the seconds in the comparison, just to avoid flakiness in tests,
+            // if for some reason execution is slow between calculation of expected and actual
+            expect(actualExpiresDate.slice(0,23)).toBe(expectedExpiresDate.slice(0,23))
+        });
 
-    }, 10_000);
-    // use 10 sec (10_000 ms) timeout for now, instead of default 5 sec to work around
-    // failing CI, because for some reason it currently takes approx. 6 secs to run
-    // TODO: actually identify what is causing this and fix the flakiness
+        it("sets the correct sesssion data", async () => {
+            // Check the session is stored in the database.
+            const { session, expiry } = await getSessionFromCookie(setCookieHeader);
+            expect(session!).toBeTruthy();
+            expect(session!.cookie.expires).toBeTruthy();
+            expect(new Date(session!.cookie.expires!).toUTCString().substring(0, 23))
+                .toBe(expectedExpiresDate.substring(0, 23));
+            expect(session!.loggedIn).toBe(true);
+            expect(expiry).toStrictEqual(new Date(session!.cookie.expires!));
+        });
 
+        it("doesn't renew the session on subsequent requests", async () => {
+            const { expiry: originalExpiry } = await getSessionFromCookie(setCookieHeader);
 
-    it("does not set Expires, when 'Remember Me' is not ticked", async () => {
+            // Simulate user waiting half the period before the session expires.
+            vi.setSystemTime(originalExpiry!.getTime() - (originalExpiry!.getTime() - Date.now()) / 2);
 
-        const res = await supertest(app)
-            .post("/login")
-            .send({ password: "demo1234" })
-            .expect(302)
+            // Make a request to renew the session.
+            await supertest(app)
+                .get("/")
+                .set("Cookie", setCookieHeader)
+                .expect(200);
 
-        const setCookieHeader = res.headers["set-cookie"][0];
+            // Check the session is still valid and has not been renewed.
+            const { session, expiry } = await getSessionFromCookie(setCookieHeader);
+            expect(session).toBeTruthy();
+            expect(expiry!.getTime()).toStrictEqual(originalExpiry!.getTime());
+        });
 
-        // match for e.g. "Expires=Wed, 07 May 2025 07:02:59 GMT;"
-        const expiresCookieRegExp = /Expires=(?[\w\s,:]+)/;
-        const expiresCookieMatch = setCookieHeader.match(expiresCookieRegExp);
-        expect(expiresCookieMatch).toBeNull();
+        it("cleans up expired sessions", async () => {
+            let { session, expiry } = await getSessionFromCookie(setCookieHeader);
+            expect(session).toBeTruthy();
+            expect(expiry).toBeTruthy();
 
-    }, 10_000);
-    // use 10 sec (10_000 ms) timeout for now, instead of default 5 sec to work around
-    // failing CI, because for some reason it currently takes approx. 6 secs to run
-    // TODO: actually identify what is causing this and fix the flakiness
+            vi.setSystemTime(expiry!);
+            vi.advanceTimersByTime(CLEAN_UP_INTERVAL);
+            ({ session } = await getSessionFromCookie(setCookieHeader));
+            expect(session).toBeFalsy();
+        });
+    });
 
+    describe("Login when 'Remember Me' is not ticked", async () => {
+        let res: Response;
+        let setCookieHeader: string;
 
-});
+        beforeAll(async () => {
+            res = await supertest(app)
+                .post("/login")
+                .send({ password: "demo1234" })
+                .expect(302)
+
+            setCookieHeader = res.headers["set-cookie"][0];
+        });
+
+        it("does not set Expires", async () => {
+            // match for e.g. "Expires=Wed, 07 May 2025 07:02:59 GMT;"
+            expect(setCookieHeader).not.toMatch(/Expires=(?[\w\s,:]+)/)
+        });
+
+        it("stores the session in the database", async () => {
+            const { session, expiry } = await getSessionFromCookie(setCookieHeader);
+            expect(session!).toBeTruthy();
+            expect(session!.cookie.expires).toBeUndefined();
+            expect(session!.loggedIn).toBe(true);
+
+            const expectedExpirationDate = dayjs().utc().add(1, "day").toDate();
+            expect(expiry?.getTime()).toBeGreaterThan(new Date().getTime());
+            expect(expiry?.getTime()).toBeLessThanOrEqual(expectedExpirationDate.getTime());
+        });
+
+        it("renews the session on subsequent requests", async () => {
+            const { expiry: originalExpiry } = await getSessionFromCookie(setCookieHeader);
+
+            // Simulate user waiting half the period before the session expires.
+            vi.setSystemTime(originalExpiry!.getTime() - (originalExpiry!.getTime() - Date.now()) / 2);
+
+            // Make a request to renew the session.
+            await supertest(app)
+                .get("/")
+                .set("Cookie", setCookieHeader)
+                .expect(200);
+
+            // Check the session is still valid and has been renewed.
+            const { session, expiry } = await getSessionFromCookie(setCookieHeader);
+            expect(session).toBeTruthy();
+            expect(expiry!.getTime()).toBeGreaterThan(originalExpiry!.getTime());
+        });
+
+        it("keeps session up to 24 hours", async () => {
+            // Simulate user waiting 23 hours.
+            vi.setSystemTime(dayjs().add(23, "hours").toDate());
+            vi.advanceTimersByTime(CLEAN_UP_INTERVAL);
+
+            // Check the session is still valid.
+            const { session } = await getSessionFromCookie(setCookieHeader);
+            expect(session).toBeTruthy();
+        });
+
+        it("cleans up expired sessions", async () => {
+            let { session, expiry } = await getSessionFromCookie(setCookieHeader);
+            expect(session).toBeTruthy();
+            expect(expiry).toBeTruthy();
+
+            vi.setSystemTime(expiry!);
+            vi.advanceTimersByTime(CLEAN_UP_INTERVAL);
+            ({ session } = await getSessionFromCookie(setCookieHeader));
+            expect(session).toBeFalsy();
+        });
+    });
+}, 100_000);
+
+async function getSessionFromCookie(setCookieHeader: string) {
+    // Extract the session ID from the cookie.
+    const sessionIdMatch = setCookieHeader.match(/trilium.sid=(?[^;]+)/)?.[1];
+    expect(sessionIdMatch).toBeTruthy();
+
+    // Check the session is stored in the database.
+    const sessionId = decodeURIComponent(sessionIdMatch!).slice(2).split(".")[0];
+    return {
+        session: await getSessionFromStore(sessionId),
+        expiry: sessionStore.getSessionExpiry(sessionId)
+    };
+}
+
+function getSessionFromStore(sessionId: string) {
+    return new Promise((resolve, reject) => {
+        sessionStore.get(sessionId, (err, session) => {
+            if (err) {
+                reject(err);
+            } else {
+                resolve(session);
+            }
+        });
+    });
+}
diff --git a/apps/server/src/routes/routes.ts b/apps/server/src/routes/routes.ts
index d9ac2c2f8..73beb28e2 100644
--- a/apps/server/src/routes/routes.ts
+++ b/apps/server/src/routes/routes.ts
@@ -400,6 +400,8 @@ function register(app: express.Application) {
     asyncApiRoute(PST, "/api/llm/embeddings/retry-all-failed", embeddingsRoute.retryAllFailedNotes);
     asyncApiRoute(PST, "/api/llm/embeddings/rebuild-index", embeddingsRoute.rebuildIndex);
     asyncApiRoute(GET, "/api/llm/embeddings/index-rebuild-status", embeddingsRoute.getIndexRebuildStatus);
+    asyncApiRoute(PST, "/api/llm/embeddings/start", embeddingsRoute.startEmbeddings);
+    asyncApiRoute(PST, "/api/llm/embeddings/stop", embeddingsRoute.stopEmbeddings);
 
     // LLM provider endpoints - moved under /api/llm/providers hierarchy
     asyncApiRoute(GET, "/api/llm/providers/ollama/models", ollamaRoute.listModels);
diff --git a/apps/server/src/routes/session_parser.ts b/apps/server/src/routes/session_parser.ts
index 240341ef7..b630b0905 100644
--- a/apps/server/src/routes/session_parser.ts
+++ b/apps/server/src/routes/session_parser.ts
@@ -5,7 +5,19 @@ import config from "../services/config.js";
 import log from "../services/log.js";
 import type express from "express";
 
-class SQLiteSessionStore extends Store {
+/**
+ * The amount of time in milliseconds after which expired sessions are cleaned up.
+ */
+export const CLEAN_UP_INTERVAL = 60 * 60 * 1000; // 1 hour
+
+/**
+ * The amount of time in milliseconds after which a session cookie expires if "Remember me" is not checked.
+ *
+ * Note that the session is renewed on each request, so the session will last up to this time from the last request.
+ */
+export const SESSION_COOKIE_EXPIRY = 24 * 60 * 60 * 1000; // 24 hours
+
+export class SQLiteSessionStore extends Store {
 
     get(sid: string, callback: (err: any, session?: session.SessionData | null) => void): void {
         try {
@@ -25,7 +37,7 @@ class SQLiteSessionStore extends Store {
         try {
             const expires = session.cookie?.expires
                 ? new Date(session.cookie.expires).getTime()
-                : Date.now() + 3600000; // fallback to 1 hour
+                : Date.now() + SESSION_COOKIE_EXPIRY;
             const data = JSON.stringify(session);
 
             sql.upsert("sessions", "id", {
@@ -50,19 +62,55 @@ class SQLiteSessionStore extends Store {
         }
     }
 
+    touch(sid: string, session: session.SessionData, callback?: (err?: any) => void): void {
+        // For now it's only for session cookies ("Remember me" unchecked).
+        if (session.cookie?.expires) {
+            callback?.();
+            return;
+        }
+
+        try {
+            const expires = Date.now() + SESSION_COOKIE_EXPIRY;
+            sql.execute(/*sql*/`UPDATE sessions SET expires = ? WHERE id = ?`, [expires, sid]);
+            callback?.();
+        } catch (e) {
+            log.error(e);
+            callback?.(e);
+        }
+    }
+
+    /**
+     * Given a session ID, returns the expiry date of the session.
+     *
+     * @param sid the session ID to check.
+     * @returns the expiry date of the session or null if the session does not exist.
+     */
+    getSessionExpiry(sid: string): Date | null {
+        try {
+            const expires = sql.getValue(/*sql*/`SELECT expires FROM sessions WHERE id = ?`, sid);
+            return expires !== undefined ? new Date(expires) : null;
+        } catch (e) {
+            log.error(e);
+            return null;
+        }
+    }
+
 }
 
+export const sessionStore = new SQLiteSessionStore();
+
 const sessionParser: express.RequestHandler = session({
     secret: sessionSecret,
     resave: false, // true forces the session to be saved back to the session store, even if the session was never modified during the request.
     saveUninitialized: false, // true forces a session that is "uninitialized" to be saved to the store. A session is uninitialized when it is new but not modified.
+    rolling: true, // forces the session to be saved back to the session store, resetting the expiration date.
     cookie: {
         path: "/",
         httpOnly: true,
         maxAge: config.Session.cookieMaxAge * 1000 // needs value in milliseconds
     },
     name: "trilium.sid",
-    store: new SQLiteSessionStore()
+    store: sessionStore
 });
 
 setInterval(() => {
@@ -70,6 +118,6 @@ setInterval(() => {
     const now = Date.now();
     const result = sql.execute(/*sql*/`DELETE FROM sessions WHERE expires < ?`, now);
     console.log("Cleaning up expired sessions: ", result.changes);
-}, 60 * 60 * 1000);
+}, CLEAN_UP_INTERVAL);
 
 export default sessionParser;
diff --git a/apps/server/src/services/llm/ai_service_manager.ts b/apps/server/src/services/llm/ai_service_manager.ts
index d7bbf4cf7..394523d8f 100644
--- a/apps/server/src/services/llm/ai_service_manager.ts
+++ b/apps/server/src/services/llm/ai_service_manager.ts
@@ -1,4 +1,5 @@
 import options from '../options.js';
+import eventService from '../events.js';
 import type { AIService, ChatCompletionOptions, ChatResponse, Message } from './ai_interface.js';
 import { AnthropicService } from './providers/anthropic_service.js';
 import { ContextExtractor } from './context/index.js';
@@ -20,9 +21,8 @@ import type { NoteSearchResult } from './interfaces/context_interfaces.js';
 
 // Import new configuration system
 import {
-    getProviderPrecedence,
-    getPreferredProvider,
-    getEmbeddingProviderPrecedence,
+    getSelectedProvider,
+    getSelectedEmbeddingProvider,
     parseModelIdentifier,
     isAIEnabled,
     getDefaultModelForProvider,
@@ -43,23 +43,20 @@ interface NoteContext {
 }
 
 export class AIServiceManager implements IAIServiceManager {
-    private services: Record = {
-        openai: new OpenAIService(),
-        anthropic: new AnthropicService(),
-        ollama: new OllamaService()
-    };
+    private services: Partial> = {};
 
-    private providerOrder: ServiceProviders[] = []; // Will be populated from configuration
     private initialized = false;
 
     constructor() {
-        // Initialize provider order immediately
-        this.updateProviderOrder();
-
         // Initialize tools immediately
         this.initializeTools().catch(error => {
             log.error(`Error initializing LLM tools during AIServiceManager construction: ${error.message || String(error)}`);
         });
+
+        // Set up event listener for provider changes
+        this.setupProviderChangeListener();
+        
+        this.initialized = true;
     }
 
     /**
@@ -84,39 +81,18 @@ export class AIServiceManager implements IAIServiceManager {
     }
 
     /**
-     * Update the provider precedence order using the new configuration system
+     * Get the currently selected provider using the new configuration system
      */
-    async updateProviderOrderAsync(): Promise {
+    async getSelectedProviderAsync(): Promise {
         try {
-            const providers = await getProviderPrecedence();
-            this.providerOrder = providers as ServiceProviders[];
-            this.initialized = true;
-            log.info(`Updated provider order: ${providers.join(', ')}`);
+            const selectedProvider = await getSelectedProvider();
+            return selectedProvider as ServiceProviders || null;
         } catch (error) {
-            log.error(`Failed to get provider precedence: ${error}`);
-            // Keep empty order, will be handled gracefully by other methods
-            this.providerOrder = [];
-            this.initialized = true;
+            log.error(`Failed to get selected provider: ${error}`);
+            return null;
         }
     }
 
-    /**
-     * Update the provider precedence order (legacy sync version)
-     * Returns true if successful, false if options not available yet
-     */
-    updateProviderOrder(): boolean {
-        if (this.initialized) {
-            return true;
-        }
-
-        // Use async version but don't wait
-        this.updateProviderOrderAsync().catch(error => {
-            log.error(`Error in async provider order update: ${error}`);
-        });
-
-        return true;
-    }
-
     /**
      * Validate AI configuration using the new configuration system
      */
@@ -158,16 +134,44 @@ export class AIServiceManager implements IAIServiceManager {
      * Ensure manager is initialized before using
      */
     private ensureInitialized() {
-        if (!this.initialized) {
-            this.updateProviderOrder();
+        // No longer needed with simplified approach
+    }
+
+    /**
+     * Get or create any available AI service following the simplified pattern
+     * Returns a service or throws a meaningful error
+     */
+    async getOrCreateAnyService(): Promise {
+        this.ensureInitialized();
+        
+        // Get the selected provider using the new configuration system
+        const selectedProvider = await this.getSelectedProviderAsync();
+        
+        
+        if (!selectedProvider) {
+            throw new Error('No AI provider is selected. Please select a provider (OpenAI, Anthropic, or Ollama) in your AI settings.');
+        }
+        
+        try {
+            const service = await this.getOrCreateChatProvider(selectedProvider);
+            if (service) {
+                return service;
+            }
+            throw new Error(`Failed to create ${selectedProvider} service`);
+        } catch (error) {
+            log.error(`Provider ${selectedProvider} not available: ${error}`);
+            throw new Error(`Selected AI provider (${selectedProvider}) is not available. Please check your configuration: ${error}`);
         }
     }
 
     /**
-     * Check if any AI service is available
+     * Check if any AI service is available (legacy method for backward compatibility)
      */
     isAnyServiceAvailable(): boolean {
-        return Object.values(this.services).some(service => service.isAvailable());
+        this.ensureInitialized();
+        
+        // Check if we have the selected provider available
+        return this.getAvailableProviders().length > 0;
     }
 
     /**
@@ -175,9 +179,42 @@ export class AIServiceManager implements IAIServiceManager {
      */
     getAvailableProviders(): ServiceProviders[] {
         this.ensureInitialized();
-        return Object.entries(this.services)
-            .filter(([_, service]) => service.isAvailable())
-            .map(([key, _]) => key as ServiceProviders);
+        
+        const allProviders: ServiceProviders[] = ['openai', 'anthropic', 'ollama'];
+        const availableProviders: ServiceProviders[] = [];
+        
+        for (const providerName of allProviders) {
+            // Use a sync approach - check if we can create the provider
+            const service = this.services[providerName];
+            if (service && service.isAvailable()) {
+                availableProviders.push(providerName);
+            } else {
+                // For providers not yet created, check configuration to see if they would be available
+                try {
+                    switch (providerName) {
+                        case 'openai':
+                            if (options.getOption('openaiApiKey')) {
+                                availableProviders.push(providerName);
+                            }
+                            break;
+                        case 'anthropic':
+                            if (options.getOption('anthropicApiKey')) {
+                                availableProviders.push(providerName);
+                            }
+                            break;
+                        case 'ollama':
+                            if (options.getOption('ollamaBaseUrl')) {
+                                availableProviders.push(providerName);
+                            }
+                            break;
+                    }
+                } catch (error) {
+                    // Ignore configuration errors, provider just won't be available
+                }
+            }
+        }
+        
+        return availableProviders;
     }
 
     /**
@@ -198,51 +235,54 @@ export class AIServiceManager implements IAIServiceManager {
             throw new Error('No messages provided for chat completion');
         }
 
-        // Try providers in order of preference
-        const availableProviders = this.getAvailableProviders();
-
-        if (availableProviders.length === 0) {
-            throw new Error('No AI providers are available. Please check your AI settings.');
+        // Get the selected provider
+        const selectedProvider = await this.getSelectedProviderAsync();
+        
+        if (!selectedProvider) {
+            throw new Error('No AI provider is selected. Please select a provider in your AI settings.');
+        }
+        
+        // Check if the selected provider is available
+        const availableProviders = this.getAvailableProviders();
+        if (!availableProviders.includes(selectedProvider)) {
+            throw new Error(`Selected AI provider (${selectedProvider}) is not available. Please check your configuration.`);
         }
-
-        // Sort available providers by precedence
-        const sortedProviders = this.providerOrder
-            .filter(provider => availableProviders.includes(provider));
 
         // If a specific provider is requested and available, use it
         if (options.model && options.model.includes(':')) {
             // Use the new configuration system to parse model identifier
             const modelIdentifier = parseModelIdentifier(options.model);
 
-            if (modelIdentifier.provider && availableProviders.includes(modelIdentifier.provider as ServiceProviders)) {
+            if (modelIdentifier.provider && modelIdentifier.provider === selectedProvider) {
                 try {
-                    const modifiedOptions = { ...options, model: modelIdentifier.modelId };
-                    log.info(`[AIServiceManager] Using provider ${modelIdentifier.provider} from model prefix with modifiedOptions.stream: ${modifiedOptions.stream}`);
-                    return await this.services[modelIdentifier.provider as ServiceProviders].generateChatCompletion(messages, modifiedOptions);
+                    const service = await this.getOrCreateChatProvider(modelIdentifier.provider as ServiceProviders);
+                    if (service) {
+                        const modifiedOptions = { ...options, model: modelIdentifier.modelId };
+                        log.info(`[AIServiceManager] Using provider ${modelIdentifier.provider} from model prefix with modifiedOptions.stream: ${modifiedOptions.stream}`);
+                        return await service.generateChatCompletion(messages, modifiedOptions);
+                    }
                 } catch (error) {
                     log.error(`Error with specified provider ${modelIdentifier.provider}: ${error}`);
-                    // If the specified provider fails, continue with the fallback providers
+                    throw new Error(`Failed to use specified provider ${modelIdentifier.provider}: ${error}`);
                 }
+            } else if (modelIdentifier.provider && modelIdentifier.provider !== selectedProvider) {
+                throw new Error(`Model specifies provider '${modelIdentifier.provider}' but selected provider is '${selectedProvider}'. Please select the correct provider or use a model without provider prefix.`);
             }
             // If not a provider prefix, treat the entire string as a model name and continue with normal provider selection
         }
 
-        // Try each provider in order until one succeeds
-        let lastError: Error | null = null;
-
-        for (const provider of sortedProviders) {
-            try {
-                log.info(`[AIServiceManager] Trying provider ${provider} with options.stream: ${options.stream}`);
-                return await this.services[provider].generateChatCompletion(messages, options);
-            } catch (error) {
-                log.error(`Error with provider ${provider}: ${error}`);
-                lastError = error as Error;
-                // Continue to the next provider
+        // Use the selected provider
+        try {
+            const service = await this.getOrCreateChatProvider(selectedProvider);
+            if (!service) {
+                throw new Error(`Failed to create selected chat provider: ${selectedProvider}. Please check your configuration.`);
             }
+            log.info(`[AIServiceManager] Using selected provider ${selectedProvider} with options.stream: ${options.stream}`);
+            return await service.generateChatCompletion(messages, options);
+        } catch (error) {
+            log.error(`Error with selected provider ${selectedProvider}: ${error}`);
+            throw new Error(`Selected AI provider (${selectedProvider}) failed: ${error}`);
         }
-
-        // If we get here, all providers failed
-        throw new Error(`All AI providers failed: ${lastError?.message || 'Unknown error'}`);
     }
 
     setupEventListeners() {
@@ -340,30 +380,64 @@ export class AIServiceManager implements IAIServiceManager {
     }
 
     /**
-     * Set up embeddings provider using the new configuration system
+     * Get or create a chat provider on-demand with inline validation
      */
-    async setupEmbeddingsProvider(): Promise {
-        try {
-            const aiEnabled = await isAIEnabled();
-            if (!aiEnabled) {
-                log.info('AI features are disabled');
-                return;
-            }
-
-            // Use the new configuration system - no string parsing!
-            const enabledProviders = await getEnabledEmbeddingProviders();
-
-            if (enabledProviders.length === 0) {
-                log.info('No embedding providers are enabled');
-                return;
-            }
-
-            // Initialize embedding providers
-            log.info('Embedding providers initialized successfully');
-        } catch (error: any) {
-            log.error(`Error setting up embedding providers: ${error.message}`);
-            throw error;
+    private async getOrCreateChatProvider(providerName: ServiceProviders): Promise {
+        // Return existing provider if already created
+        if (this.services[providerName]) {
+            return this.services[providerName];
         }
+
+        // Create and validate provider on-demand
+        try {
+            let service: AIService | null = null;
+            
+            switch (providerName) {
+                case 'openai': {
+                    const apiKey = options.getOption('openaiApiKey');
+                    const baseUrl = options.getOption('openaiBaseUrl');
+                    if (!apiKey && !baseUrl) return null;
+                    
+                    service = new OpenAIService();
+                    // Validate by checking if it's available
+                    if (!service.isAvailable()) {
+                        throw new Error('OpenAI service not available');
+                    }
+                    break;
+                }
+                
+                case 'anthropic': {
+                    const apiKey = options.getOption('anthropicApiKey');
+                    if (!apiKey) return null;
+                    
+                    service = new AnthropicService();
+                    if (!service.isAvailable()) {
+                        throw new Error('Anthropic service not available');
+                    }
+                    break;
+                }
+                
+                case 'ollama': {
+                    const baseUrl = options.getOption('ollamaBaseUrl');
+                    if (!baseUrl) return null;
+                    
+                    service = new OllamaService();
+                    if (!service.isAvailable()) {
+                        throw new Error('Ollama service not available');
+                    }
+                    break;
+                }
+            }
+            
+            if (service) {
+                this.services[providerName] = service;
+                return service;
+            }
+        } catch (error: any) {
+            log.error(`Failed to create ${providerName} chat provider: ${error.message || 'Unknown error'}`);
+        }
+
+        return null;
     }
 
     /**
@@ -381,12 +455,6 @@ export class AIServiceManager implements IAIServiceManager {
                 return;
             }
 
-            // Update provider order from configuration
-            await this.updateProviderOrderAsync();
-
-            // Set up embeddings provider if AI is enabled
-            await this.setupEmbeddingsProvider();
-
             // Initialize index service
             await this.getIndexService().initialize();
 
@@ -453,8 +521,8 @@ export class AIServiceManager implements IAIServiceManager {
             if (!contextNotes || contextNotes.length === 0) {
                 try {
                     // Get the default LLM service for context enhancement
-                    const provider = this.getPreferredProvider();
-                    const llmService = this.getService(provider);
+                    const provider = this.getSelectedProvider();
+                    const llmService = await this.getService(provider);
 
                     // Find relevant notes
                     contextNotes = await contextService.findRelevantNotes(
@@ -495,25 +563,31 @@ export class AIServiceManager implements IAIServiceManager {
     /**
      * Get AI service for the given provider
      */
-    getService(provider?: string): AIService {
+    async getService(provider?: string): Promise {
         this.ensureInitialized();
 
-        // If provider is specified, try to use it
-        if (provider && this.services[provider as ServiceProviders]?.isAvailable()) {
-            return this.services[provider as ServiceProviders];
-        }
-
-        // Otherwise, use the first available provider in the configured order
-        for (const providerName of this.providerOrder) {
-            const service = this.services[providerName];
-            if (service.isAvailable()) {
+        // If provider is specified, try to get or create it
+        if (provider) {
+            const service = await this.getOrCreateChatProvider(provider as ServiceProviders);
+            if (service && service.isAvailable()) {
                 return service;
             }
+            throw new Error(`Specified provider ${provider} is not available`);
         }
 
-        // If no provider is available, use first one anyway (it will throw an error)
-        // This allows us to show a proper error message rather than "provider not found"
-        return this.services[this.providerOrder[0]];
+        // Otherwise, use the selected provider
+        const selectedProvider = await this.getSelectedProviderAsync();
+        if (!selectedProvider) {
+            throw new Error('No AI provider is selected. Please select a provider in your AI settings.');
+        }
+
+        const service = await this.getOrCreateChatProvider(selectedProvider);
+        if (service && service.isAvailable()) {
+            return service;
+        }
+
+        // If no provider is available, throw a clear error
+        throw new Error(`Selected AI provider (${selectedProvider}) is not available. Please check your AI settings.`);
     }
 
     /**
@@ -521,34 +595,37 @@ export class AIServiceManager implements IAIServiceManager {
      */
     async getPreferredProviderAsync(): Promise {
         try {
-            const preferredProvider = await getPreferredProvider();
-            if (preferredProvider === null) {
-                // No providers configured, fallback to first available
-                log.info('No providers configured in precedence, using first available provider');
-                return this.providerOrder[0];
+            const selectedProvider = await getSelectedProvider();
+            if (selectedProvider === null) {
+                // No provider selected, fallback to default
+                log.info('No provider selected, using default provider');
+                return 'openai';
             }
-            return preferredProvider;
+            return selectedProvider;
         } catch (error) {
             log.error(`Error getting preferred provider: ${error}`);
-            return this.providerOrder[0];
+            return 'openai';
         }
     }
 
     /**
-     * Get the preferred provider based on configuration (sync version for compatibility)
+     * Get the selected provider based on configuration (sync version for compatibility)
      */
-    getPreferredProvider(): string {
+    getSelectedProvider(): string {
         this.ensureInitialized();
 
-        // Return the first available provider in the order
-        for (const providerName of this.providerOrder) {
-            if (this.services[providerName].isAvailable()) {
-                return providerName;
+        // Try to get the selected provider synchronously
+        try {
+            const selectedProvider = options.getOption('aiSelectedProvider');
+            if (selectedProvider) {
+                return selectedProvider;
             }
+        } catch (error) {
+            log.error(`Error getting selected provider: ${error}`);
         }
 
-        // Return the first provider as fallback
-        return this.providerOrder[0];
+        // Return a default if nothing is selected (for backward compatibility)
+        return 'openai';
     }
 
     /**
@@ -580,6 +657,7 @@ export class AIServiceManager implements IAIServiceManager {
         };
     }
 
+
     /**
      * Error handler that properly types the error object
      */
@@ -589,6 +667,79 @@ export class AIServiceManager implements IAIServiceManager {
         }
         return String(error);
     }
+
+    /**
+     * Set up event listener for provider changes
+     */
+    private setupProviderChangeListener(): void {
+        // List of AI-related options that should trigger service recreation
+        const aiRelatedOptions = [
+            'aiEnabled',
+            'aiSelectedProvider',
+            'embeddingSelectedProvider',
+            'openaiApiKey',
+            'openaiBaseUrl', 
+            'openaiDefaultModel',
+            'anthropicApiKey',
+            'anthropicBaseUrl',
+            'anthropicDefaultModel',
+            'ollamaBaseUrl',
+            'ollamaDefaultModel',
+            'voyageApiKey'
+        ];
+
+        eventService.subscribe(['entityChanged'], async ({ entityName, entity }) => {
+            if (entityName === 'options' && entity && aiRelatedOptions.includes(entity.name)) {
+                log.info(`AI-related option '${entity.name}' changed, recreating LLM services`);
+                
+                // Special handling for aiEnabled toggle
+                if (entity.name === 'aiEnabled') {
+                    const isEnabled = entity.value === 'true';
+                    
+                    if (isEnabled) {
+                        log.info('AI features enabled, initializing AI service and embeddings');
+                        // Initialize the AI service
+                        await this.initialize();
+                        // Initialize embeddings through index service
+                        await indexService.startEmbeddingGeneration();
+                    } else {
+                        log.info('AI features disabled, stopping embeddings and clearing providers');
+                        // Stop embeddings through index service
+                        await indexService.stopEmbeddingGeneration();
+                        // Clear chat providers
+                        this.services = {};
+                    }
+                } else {
+                    // For other AI-related options, recreate services on-demand
+                    await this.recreateServices();
+                }
+            }
+        });
+    }
+
+    /**
+     * Recreate LLM services when provider settings change
+     */
+    private async recreateServices(): Promise {
+        try {
+            log.info('Recreating LLM services due to configuration change');
+
+            // Clear configuration cache first
+            clearConfigurationCache();
+
+            // Clear existing chat providers (they will be recreated on-demand)
+            this.services = {};
+
+            // Clear embedding providers (they will be recreated on-demand when needed)
+            const providerManager = await import('./providers/providers.js');
+            providerManager.clearAllEmbeddingProviders();
+
+            log.info('LLM services recreated successfully');
+        } catch (error) {
+            log.error(`Error recreating LLM services: ${this.handleError(error)}`);
+        }
+    }
+
 }
 
 // Don't create singleton immediately, use a lazy-loading pattern
@@ -610,6 +761,9 @@ export default {
     isAnyServiceAvailable(): boolean {
         return getInstance().isAnyServiceAvailable();
     },
+    async getOrCreateAnyService(): Promise {
+        return getInstance().getOrCreateAnyService();
+    },
     getAvailableProviders() {
         return getInstance().getAvailableProviders();
     },
@@ -661,11 +815,11 @@ export default {
         );
     },
     // New methods
-    getService(provider?: string): AIService {
+    async getService(provider?: string): Promise {
         return getInstance().getService(provider);
     },
-    getPreferredProvider(): string {
-        return getInstance().getPreferredProvider();
+    getSelectedProvider(): string {
+        return getInstance().getSelectedProvider();
     },
     isProviderAvailable(provider: string): boolean {
         return getInstance().isProviderAvailable(provider);
diff --git a/apps/server/src/services/llm/chat/rest_chat_service.ts b/apps/server/src/services/llm/chat/rest_chat_service.ts
index 1ad3d7a22..53ea457a1 100644
--- a/apps/server/src/services/llm/chat/rest_chat_service.ts
+++ b/apps/server/src/services/llm/chat/rest_chat_service.ts
@@ -5,7 +5,7 @@
 import log from "../../log.js";
 import type { Request, Response } from "express";
 import type { Message, ChatCompletionOptions } from "../ai_interface.js";
-import { AIServiceManager } from "../ai_service_manager.js";
+import aiServiceManager from "../ai_service_manager.js";
 import { ChatPipeline } from "../pipeline/chat_pipeline.js";
 import type { ChatPipelineInput } from "../pipeline/interfaces.js";
 import options from "../../options.js";
@@ -14,7 +14,7 @@ import type { LLMStreamMessage } from "../interfaces/chat_ws_messages.js";
 import chatStorageService from '../chat_storage_service.js';
 import {
     isAIEnabled,
-    getFirstValidModelConfig,
+    getSelectedModelConfig,
 } from '../config/configuration_helpers.js';
 
 /**
@@ -33,25 +33,6 @@ class RestChatService {
         }
     }
 
-    /**
-     * Check if AI services are available
-     */
-    safelyUseAIManager(): boolean {
-        if (!this.isDatabaseInitialized()) {
-            log.info("AI check failed: Database is not initialized");
-            return false;
-        }
-
-        try {
-            const aiManager = new AIServiceManager();
-            const isAvailable = aiManager.isAnyServiceAvailable();
-            log.info(`AI service availability check result: ${isAvailable}`);
-            return isAvailable;
-        } catch (error) {
-            log.error(`Error accessing AI service manager: ${error}`);
-            return false;
-        }
-    }
 
     /**
      * Handle a message sent to an LLM and get a response
@@ -93,10 +74,14 @@ class RestChatService {
                 return { error: "AI features are disabled. Please enable them in the settings." };
             }
 
-            if (!this.safelyUseAIManager()) {
-                return { error: "AI services are currently unavailable. Please check your configuration." };
+            // Check database initialization first
+            if (!this.isDatabaseInitialized()) {
+                throw new Error("Database is not initialized");
             }
 
+            // Get or create AI service - will throw meaningful error if not possible  
+            await aiServiceManager.getOrCreateAnyService();
+
             // Load or create chat directly from storage
             let chat = await chatStorageService.getChat(chatNoteId);
 
@@ -252,14 +237,6 @@ class RestChatService {
 
         // Send WebSocket message
         wsService.sendMessageToAllClients(message);
-
-        // Send SSE response for compatibility
-        const responseData: any = { content: data, done };
-        if (rawChunk?.toolExecution) {
-            responseData.toolExecution = rawChunk.toolExecution;
-        }
-
-        res.write(`data: ${JSON.stringify(responseData)}\n\n`);
         
         // When streaming is complete, save the accumulated content to the chat note
         if (done) {
@@ -281,8 +258,8 @@ class RestChatService {
                 log.error(`Error saving streaming response: ${error}`);
             }
             
-            // End the response
-            res.end();
+            // Note: For WebSocket-only streaming, we don't end the HTTP response here
+            // since it was already handled by the calling endpoint
         }
     }
 
@@ -419,7 +396,7 @@ class RestChatService {
      */
     async getPreferredModel(): Promise {
         try {
-            const validConfig = await getFirstValidModelConfig();
+            const validConfig = await getSelectedModelConfig();
             if (!validConfig) {
                 log.error('No valid AI model configuration found');
                 return undefined;
diff --git a/apps/server/src/services/llm/config/configuration_helpers.ts b/apps/server/src/services/llm/config/configuration_helpers.ts
index 88d2cf1da..2635cc35f 100644
--- a/apps/server/src/services/llm/config/configuration_helpers.ts
+++ b/apps/server/src/services/llm/config/configuration_helpers.ts
@@ -1,10 +1,9 @@
 import configurationManager from './configuration_manager.js';
+import optionService from '../../options.js';
 import type {
     ProviderType,
     ModelIdentifier,
     ModelConfig,
-    ProviderPrecedenceConfig,
-    EmbeddingProviderPrecedenceConfig
 } from '../interfaces/configuration_interfaces.js';
 
 /**
@@ -13,41 +12,19 @@ import type {
  */
 
 /**
- * Get the ordered list of AI providers
+ * Get the selected AI provider
  */
-export async function getProviderPrecedence(): Promise {
-    const config = await configurationManager.getProviderPrecedence();
-    return config.providers;
+export async function getSelectedProvider(): Promise {
+    const providerOption = optionService.getOption('aiSelectedProvider');
+    return providerOption as ProviderType || null;
 }
 
 /**
- * Get the default/preferred AI provider
+ * Get the selected embedding provider
  */
-export async function getPreferredProvider(): Promise {
-    const config = await configurationManager.getProviderPrecedence();
-    if (config.providers.length === 0) {
-        return null; // No providers configured
-    }
-    return config.defaultProvider || config.providers[0];
-}
-
-/**
- * Get the ordered list of embedding providers
- */
-export async function getEmbeddingProviderPrecedence(): Promise {
-    const config = await configurationManager.getEmbeddingProviderPrecedence();
-    return config.providers;
-}
-
-/**
- * Get the default embedding provider
- */
-export async function getPreferredEmbeddingProvider(): Promise {
-    const config = await configurationManager.getEmbeddingProviderPrecedence();
-    if (config.providers.length === 0) {
-        return null; // No providers configured
-    }
-    return config.defaultProvider || config.providers[0];
+export async function getSelectedEmbeddingProvider(): Promise {
+    const providerOption = optionService.getOption('embeddingSelectedProvider');
+    return providerOption || null;
 }
 
 /**
@@ -107,22 +84,20 @@ export async function isProviderConfigured(provider: ProviderType): Promise {
-    const providers = await getProviderPrecedence();
-
-    if (providers.length === 0) {
-        return null; // No providers configured
+export async function getAvailableSelectedProvider(): Promise {
+    const selectedProvider = await getSelectedProvider();
+    
+    if (!selectedProvider) {
+        return null; // No provider selected
     }
 
-    for (const provider of providers) {
-        if (await isProviderConfigured(provider)) {
-            return provider;
-        }
+    if (await isProviderConfigured(selectedProvider)) {
+        return selectedProvider;
     }
 
-    return null; // No providers are properly configured
+    return null; // Selected provider is not properly configured
 }
 
 /**
@@ -163,17 +138,15 @@ export async function getValidModelConfig(provider: ProviderType): Promise<{ mod
 }
 
 /**
- * Get the first valid model configuration from the provider precedence list
+ * Get the model configuration for the currently selected provider
  */
-export async function getFirstValidModelConfig(): Promise<{ model: string; provider: ProviderType } | null> {
-    const providers = await getProviderPrecedence();
-
-    for (const provider of providers) {
-        const config = await getValidModelConfig(provider);
-        if (config) {
-            return config;
-        }
+export async function getSelectedModelConfig(): Promise<{ model: string; provider: ProviderType } | null> {
+    const selectedProvider = await getSelectedProvider();
+    
+    if (!selectedProvider) {
+        return null; // No provider selected
     }
 
-    return null; // No valid model configuration found
+    return await getValidModelConfig(selectedProvider);
 }
+
diff --git a/apps/server/src/services/llm/config/configuration_manager.ts b/apps/server/src/services/llm/config/configuration_manager.ts
index 5bc9611b8..1e082db41 100644
--- a/apps/server/src/services/llm/config/configuration_manager.ts
+++ b/apps/server/src/services/llm/config/configuration_manager.ts
@@ -50,8 +50,8 @@ export class ConfigurationManager {
         try {
             const config: AIConfig = {
                 enabled: await this.getAIEnabled(),
-                providerPrecedence: await this.getProviderPrecedence(),
-                embeddingProviderPrecedence: await this.getEmbeddingProviderPrecedence(),
+                selectedProvider: await this.getSelectedProvider(),
+                selectedEmbeddingProvider: await this.getSelectedEmbeddingProvider(),
                 defaultModels: await this.getDefaultModels(),
                 providerSettings: await this.getProviderSettings()
             };
@@ -66,46 +66,28 @@ export class ConfigurationManager {
     }
 
     /**
-     * Parse provider precedence from string option
+     * Get the selected AI provider
      */
-    public async getProviderPrecedence(): Promise {
+    public async getSelectedProvider(): Promise {
         try {
-            const precedenceOption = await options.getOption('aiProviderPrecedence');
-            const providers = this.parseProviderList(precedenceOption);
-
-            return {
-                providers: providers as ProviderType[],
-                defaultProvider: providers.length > 0 ? providers[0] as ProviderType : undefined
-            };
+            const selectedProvider = options.getOption('aiSelectedProvider');
+            return selectedProvider as ProviderType || null;
         } catch (error) {
-            log.error(`Error parsing provider precedence: ${error}`);
-            // Only return known providers if they exist, don't assume defaults
-            return {
-                providers: [],
-                defaultProvider: undefined
-            };
+            log.error(`Error getting selected provider: ${error}`);
+            return null;
         }
     }
 
     /**
-     * Parse embedding provider precedence from string option
+     * Get the selected embedding provider
      */
-    public async getEmbeddingProviderPrecedence(): Promise {
+    public async getSelectedEmbeddingProvider(): Promise {
         try {
-            const precedenceOption = await options.getOption('embeddingProviderPrecedence');
-            const providers = this.parseProviderList(precedenceOption);
-
-            return {
-                providers: providers as EmbeddingProviderType[],
-                defaultProvider: providers.length > 0 ? providers[0] as EmbeddingProviderType : undefined
-            };
+            const selectedProvider = options.getOption('embeddingSelectedProvider');
+            return selectedProvider as EmbeddingProviderType || null;
         } catch (error) {
-            log.error(`Error parsing embedding provider precedence: ${error}`);
-            // Don't assume defaults, return empty configuration
-            return {
-                providers: [],
-                defaultProvider: undefined
-            };
+            log.error(`Error getting selected embedding provider: ${error}`);
+            return null;
         }
     }
 
@@ -173,11 +155,9 @@ export class ConfigurationManager {
      */
     public async getDefaultModels(): Promise> {
         try {
-            const [openaiModel, anthropicModel, ollamaModel] = await Promise.all([
-                options.getOption('openaiDefaultModel'),
-                options.getOption('anthropicDefaultModel'),
-                options.getOption('ollamaDefaultModel')
-            ]);
+            const openaiModel = options.getOption('openaiDefaultModel');
+            const anthropicModel = options.getOption('anthropicDefaultModel');
+            const ollamaModel = options.getOption('ollamaDefaultModel');
 
             return {
                 openai: openaiModel || undefined,
@@ -200,20 +180,14 @@ export class ConfigurationManager {
      */
     public async getProviderSettings(): Promise {
         try {
-            const [
-                openaiApiKey, openaiBaseUrl, openaiDefaultModel,
-                anthropicApiKey, anthropicBaseUrl, anthropicDefaultModel,
-                ollamaBaseUrl, ollamaDefaultModel
-            ] = await Promise.all([
-                options.getOption('openaiApiKey'),
-                options.getOption('openaiBaseUrl'),
-                options.getOption('openaiDefaultModel'),
-                options.getOption('anthropicApiKey'),
-                options.getOption('anthropicBaseUrl'),
-                options.getOption('anthropicDefaultModel'),
-                options.getOption('ollamaBaseUrl'),
-                options.getOption('ollamaDefaultModel')
-            ]);
+            const openaiApiKey = options.getOption('openaiApiKey');
+            const openaiBaseUrl = options.getOption('openaiBaseUrl');
+            const openaiDefaultModel = options.getOption('openaiDefaultModel');
+            const anthropicApiKey = options.getOption('anthropicApiKey');
+            const anthropicBaseUrl = options.getOption('anthropicBaseUrl');
+            const anthropicDefaultModel = options.getOption('anthropicDefaultModel');
+            const ollamaBaseUrl = options.getOption('ollamaBaseUrl');
+            const ollamaDefaultModel = options.getOption('ollamaDefaultModel');
 
             const settings: ProviderSettings = {};
 
@@ -265,31 +239,29 @@ export class ConfigurationManager {
                 return result;
             }
 
-            // Validate provider precedence
-            if (config.providerPrecedence.providers.length === 0) {
-                result.errors.push('No providers configured in precedence list');
+            // Validate selected provider
+            if (!config.selectedProvider) {
+                result.errors.push('No AI provider selected');
                 result.isValid = false;
-            }
+            } else {
+                // Validate selected provider settings
+                const providerConfig = config.providerSettings[config.selectedProvider];
 
-            // Validate provider settings
-            for (const provider of config.providerPrecedence.providers) {
-                const providerConfig = config.providerSettings[provider];
-
-                if (provider === 'openai') {
+                if (config.selectedProvider === 'openai') {
                     const openaiConfig = providerConfig as OpenAISettings | undefined;
                     if (!openaiConfig?.apiKey) {
                         result.warnings.push('OpenAI API key is not configured');
                     }
                 }
 
-                if (provider === 'anthropic') {
+                if (config.selectedProvider === 'anthropic') {
                     const anthropicConfig = providerConfig as AnthropicSettings | undefined;
                     if (!anthropicConfig?.apiKey) {
                         result.warnings.push('Anthropic API key is not configured');
                     }
                 }
 
-                if (provider === 'ollama') {
+                if (config.selectedProvider === 'ollama') {
                     const ollamaConfig = providerConfig as OllamaSettings | undefined;
                     if (!ollamaConfig?.baseUrl) {
                         result.warnings.push('Ollama base URL is not configured');
@@ -297,6 +269,11 @@ export class ConfigurationManager {
                 }
             }
 
+            // Validate selected embedding provider
+            if (!config.selectedEmbeddingProvider) {
+                result.warnings.push('No embedding provider selected');
+            }
+
         } catch (error) {
             result.errors.push(`Configuration validation error: ${error}`);
             result.isValid = false;
@@ -317,7 +294,7 @@ export class ConfigurationManager {
 
     private async getAIEnabled(): Promise {
         try {
-            return await options.getOptionBool('aiEnabled');
+            return options.getOptionBool('aiEnabled');
         } catch {
             return false;
         }
@@ -356,14 +333,8 @@ export class ConfigurationManager {
     private getDefaultConfig(): AIConfig {
         return {
             enabled: false,
-            providerPrecedence: {
-                providers: [],
-                defaultProvider: undefined
-            },
-            embeddingProviderPrecedence: {
-                providers: [],
-                defaultProvider: undefined
-            },
+            selectedProvider: null,
+            selectedEmbeddingProvider: null,
             defaultModels: {
                 openai: undefined,
                 anthropic: undefined,
diff --git a/apps/server/src/services/llm/context/index.ts b/apps/server/src/services/llm/context/index.ts
index 258428705..c44eea9cb 100644
--- a/apps/server/src/services/llm/context/index.ts
+++ b/apps/server/src/services/llm/context/index.ts
@@ -33,7 +33,7 @@ async function getSemanticContext(
         }
 
         // Get an LLM service
-        const llmService = aiServiceManager.getInstance().getService();
+        const llmService = await aiServiceManager.getInstance().getService();
 
         const result = await contextService.processQuery("", llmService, {
             maxResults: options.maxSimilarNotes || 5,
@@ -543,7 +543,7 @@ export class ContextExtractor {
         try {
             const { default: aiServiceManager } = await import('../ai_service_manager.js');
             const contextService = aiServiceManager.getInstance().getContextService();
-            const llmService = aiServiceManager.getInstance().getService();
+            const llmService = await aiServiceManager.getInstance().getService();
 
             if (!contextService) {
                 return "Context service not available.";
diff --git a/apps/server/src/services/llm/context/modules/provider_manager.ts b/apps/server/src/services/llm/context/modules/provider_manager.ts
index 8030e3592..56c6437c0 100644
--- a/apps/server/src/services/llm/context/modules/provider_manager.ts
+++ b/apps/server/src/services/llm/context/modules/provider_manager.ts
@@ -1,51 +1,32 @@
-import options from '../../../options.js';
 import log from '../../../log.js';
 import { getEmbeddingProvider, getEnabledEmbeddingProviders } from '../../providers/providers.js';
+import { getSelectedEmbeddingProvider as getSelectedEmbeddingProviderName } from '../../config/configuration_helpers.js';
 
 /**
  * Manages embedding providers for context services
  */
 export class ProviderManager {
     /**
-     * Get the preferred embedding provider based on user settings
-     * Tries to use the most appropriate provider in this order:
-     * 1. User's configured default provider
-     * 2. OpenAI if API key is set
-     * 3. Anthropic if API key is set
-     * 4. Ollama if configured
-     * 5. Any available provider
-     * 6. Local provider as fallback
+     * Get the selected embedding provider based on user settings
+     * Uses the single provider selection approach
      *
-     * @returns The preferred embedding provider or null if none available
+     * @returns The selected embedding provider or null if none available
      */
-    async getPreferredEmbeddingProvider(): Promise {
+    async getSelectedEmbeddingProvider(): Promise {
         try {
-            // Try to get providers based on precedence list
-            const precedenceOption = await options.getOption('embeddingProviderPrecedence');
-            let precedenceList: string[] = [];
-
-            if (precedenceOption) {
-                if (precedenceOption.startsWith('[') && precedenceOption.endsWith(']')) {
-                    precedenceList = JSON.parse(precedenceOption);
-                } else if (typeof precedenceOption === 'string') {
-                    if (precedenceOption.includes(',')) {
-                        precedenceList = precedenceOption.split(',').map(p => p.trim());
-                    } else {
-                        precedenceList = [precedenceOption];
-                    }
-                }
-            }
-
-            // Try each provider in the precedence list
-            for (const providerId of precedenceList) {
-                const provider = await getEmbeddingProvider(providerId);
+            // Get the selected embedding provider
+            const selectedProvider = await getSelectedEmbeddingProviderName();
+            
+            if (selectedProvider) {
+                const provider = await getEmbeddingProvider(selectedProvider);
                 if (provider) {
-                    log.info(`Using embedding provider from precedence list: ${providerId}`);
+                    log.info(`Using selected embedding provider: ${selectedProvider}`);
                     return provider;
                 }
+                log.info(`Selected embedding provider ${selectedProvider} is not available`);
             }
 
-            // If no provider from precedence list is available, try any enabled provider
+            // If no provider is selected or available, try any enabled provider
             const providers = await getEnabledEmbeddingProviders();
             if (providers.length > 0) {
                 log.info(`Using available embedding provider: ${providers[0].name}`);
@@ -70,7 +51,7 @@ export class ProviderManager {
     async generateQueryEmbedding(query: string): Promise {
         try {
             // Get the preferred embedding provider
-            const provider = await this.getPreferredEmbeddingProvider();
+            const provider = await this.getSelectedEmbeddingProvider();
             if (!provider) {
                 log.error('No embedding provider available');
                 return null;
diff --git a/apps/server/src/services/llm/context/services/context_service.ts b/apps/server/src/services/llm/context/services/context_service.ts
index a227c3936..b4d4fd613 100644
--- a/apps/server/src/services/llm/context/services/context_service.ts
+++ b/apps/server/src/services/llm/context/services/context_service.ts
@@ -58,7 +58,7 @@ export class ContextService {
         this.initPromise = (async () => {
             try {
                 // Initialize provider
-                const provider = await providerManager.getPreferredEmbeddingProvider();
+                const provider = await providerManager.getSelectedEmbeddingProvider();
                 if (!provider) {
                     throw new Error(`No embedding provider available. Could not initialize context service.`);
                 }
@@ -224,7 +224,7 @@ export class ContextService {
             log.info(`Final combined results: ${relevantNotes.length} relevant notes`);
 
             // Step 4: Build context from the notes
-            const provider = await providerManager.getPreferredEmbeddingProvider();
+            const provider = await providerManager.getSelectedEmbeddingProvider();
             const providerId = provider?.name || 'default';
 
             const context = await contextFormatter.buildContextFromNotes(
diff --git a/apps/server/src/services/llm/context/services/vector_search_service.ts b/apps/server/src/services/llm/context/services/vector_search_service.ts
index 480ba05bd..98c7b993c 100644
--- a/apps/server/src/services/llm/context/services/vector_search_service.ts
+++ b/apps/server/src/services/llm/context/services/vector_search_service.ts
@@ -79,7 +79,7 @@ export class VectorSearchService {
             }
 
             // Get provider information
-            const provider = await providerManager.getPreferredEmbeddingProvider();
+            const provider = await providerManager.getSelectedEmbeddingProvider();
             if (!provider) {
                 log.error('No embedding provider available');
                 return [];
@@ -280,7 +280,7 @@ export class VectorSearchService {
             }
 
             // Get provider information
-            const provider = await providerManager.getPreferredEmbeddingProvider();
+            const provider = await providerManager.getSelectedEmbeddingProvider();
             if (!provider) {
                 log.error('No embedding provider available');
                 return [];
diff --git a/apps/server/src/services/llm/embeddings/events.ts b/apps/server/src/services/llm/embeddings/events.ts
index a078b2c32..2b8eac7d9 100644
--- a/apps/server/src/services/llm/embeddings/events.ts
+++ b/apps/server/src/services/llm/embeddings/events.ts
@@ -9,6 +9,9 @@ import becca from "../../../becca/becca.js";
 // Add mutex to prevent concurrent processing
 let isProcessingEmbeddings = false;
 
+// Store interval reference for cleanup
+let backgroundProcessingInterval: NodeJS.Timeout | null = null;
+
 /**
  * Setup event listeners for embedding-related events
  */
@@ -53,9 +56,15 @@ export function setupEmbeddingEventListeners() {
  * Setup background processing of the embedding queue
  */
 export async function setupEmbeddingBackgroundProcessing() {
+    // Clear any existing interval
+    if (backgroundProcessingInterval) {
+        clearInterval(backgroundProcessingInterval);
+        backgroundProcessingInterval = null;
+    }
+
     const interval = parseInt(await options.getOption('embeddingUpdateInterval') || '200', 10);
 
-    setInterval(async () => {
+    backgroundProcessingInterval = setInterval(async () => {
         try {
             // Skip if already processing
             if (isProcessingEmbeddings) {
@@ -78,6 +87,17 @@ export async function setupEmbeddingBackgroundProcessing() {
     }, interval);
 }
 
+/**
+ * Stop background processing of the embedding queue
+ */
+export function stopEmbeddingBackgroundProcessing() {
+    if (backgroundProcessingInterval) {
+        clearInterval(backgroundProcessingInterval);
+        backgroundProcessingInterval = null;
+        log.info("Embedding background processing stopped");
+    }
+}
+
 /**
  * Initialize embeddings system
  */
diff --git a/apps/server/src/services/llm/embeddings/index.ts b/apps/server/src/services/llm/embeddings/index.ts
index 89d0f711e..c4be44a2e 100644
--- a/apps/server/src/services/llm/embeddings/index.ts
+++ b/apps/server/src/services/llm/embeddings/index.ts
@@ -58,12 +58,12 @@ export const processNoteWithChunking = async (
 export const {
     setupEmbeddingEventListeners,
     setupEmbeddingBackgroundProcessing,
+    stopEmbeddingBackgroundProcessing,
     initEmbeddings
 } = events;
 
 export const {
     getEmbeddingStats,
-    reprocessAllNotes,
     cleanupEmbeddings
 } = stats;
 
@@ -100,11 +100,11 @@ export default {
     // Event handling
     setupEmbeddingEventListeners: events.setupEmbeddingEventListeners,
     setupEmbeddingBackgroundProcessing: events.setupEmbeddingBackgroundProcessing,
+    stopEmbeddingBackgroundProcessing: events.stopEmbeddingBackgroundProcessing,
     initEmbeddings: events.initEmbeddings,
 
     // Stats and maintenance
     getEmbeddingStats: stats.getEmbeddingStats,
-    reprocessAllNotes: stats.reprocessAllNotes,
     cleanupEmbeddings: stats.cleanupEmbeddings,
 
     // Index operations
diff --git a/apps/server/src/services/llm/embeddings/init.ts b/apps/server/src/services/llm/embeddings/init.ts
index 50724c05e..75d664e43 100644
--- a/apps/server/src/services/llm/embeddings/init.ts
+++ b/apps/server/src/services/llm/embeddings/init.ts
@@ -4,6 +4,7 @@ import { initEmbeddings } from "./index.js";
 import providerManager from "../providers/providers.js";
 import sqlInit from "../../sql_init.js";
 import sql from "../../sql.js";
+import { validateProviders, logValidationResults, hasWorkingEmbeddingProviders } from "../provider_validation.js";
 
 /**
  * Reset any stuck embedding queue items that were left in processing state
@@ -43,13 +44,20 @@ export async function initializeEmbeddings() {
         // Reset any stuck embedding queue items from previous server shutdown
         await resetStuckEmbeddingQueue();
 
-        // Initialize default embedding providers
-        await providerManager.initializeDefaultProviders();
-
         // Start the embedding system if AI is enabled
         if (await options.getOptionBool('aiEnabled')) {
-            await initEmbeddings();
-            log.info("Embedding system initialized successfully.");
+            // Validate providers before starting the embedding system
+            log.info("Validating AI providers before starting embedding system...");
+            const validation = await validateProviders();
+            logValidationResults(validation);
+            
+            if (await hasWorkingEmbeddingProviders()) {
+                // Embedding providers will be created on-demand when needed
+                await initEmbeddings();
+                log.info("Embedding system initialized successfully.");
+            } else {
+                log.info("Embedding system not started: No working embedding providers found. Please configure at least one AI provider (OpenAI, Ollama, or Voyage) to use embedding features.");
+            }
         } else {
             log.info("Embedding system disabled (AI features are turned off).");
         }
diff --git a/apps/server/src/services/llm/embeddings/queue.ts b/apps/server/src/services/llm/embeddings/queue.ts
index 12f915c81..b002513c5 100644
--- a/apps/server/src/services/llm/embeddings/queue.ts
+++ b/apps/server/src/services/llm/embeddings/queue.ts
@@ -282,8 +282,6 @@ export async function processEmbeddingQueue() {
                 continue;
             }
 
-            // Log that we're starting to process this note
-            log.info(`Starting embedding generation for note ${noteId}`);
 
             // Get note context for embedding
             const context = await getNoteEmbeddingContext(noteId);
@@ -334,7 +332,6 @@ export async function processEmbeddingQueue() {
                     "DELETE FROM embedding_queue WHERE noteId = ?",
                     [noteId]
                 );
-                log.info(`Successfully completed embedding processing for note ${noteId}`);
 
                 // Count as successfully processed
                 processedCount++;
diff --git a/apps/server/src/services/llm/embeddings/stats.ts b/apps/server/src/services/llm/embeddings/stats.ts
index 6154da368..a8b594723 100644
--- a/apps/server/src/services/llm/embeddings/stats.ts
+++ b/apps/server/src/services/llm/embeddings/stats.ts
@@ -1,29 +1,5 @@
 import sql from "../../../services/sql.js";
 import log from "../../../services/log.js";
-import cls from "../../../services/cls.js";
-import { queueNoteForEmbedding } from "./queue.js";
-
-/**
- * Reprocess all notes to update embeddings
- */
-export async function reprocessAllNotes() {
-    log.info("Queueing all notes for embedding updates");
-
-    // Get all non-deleted note IDs
-    const noteIds = await sql.getColumn(
-        "SELECT noteId FROM notes WHERE isDeleted = 0"
-    );
-
-    log.info(`Adding ${noteIds.length} notes to embedding queue`);
-
-    // Process each note ID within a cls context
-    for (const noteId of noteIds) {
-        // Use cls.init to ensure proper context for each operation
-        await cls.init(async () => {
-            await queueNoteForEmbedding(noteId as string, 'UPDATE');
-        });
-    }
-}
 
 /**
  * Get current embedding statistics
diff --git a/apps/server/src/services/llm/embeddings/storage.ts b/apps/server/src/services/llm/embeddings/storage.ts
index ac096071f..bbd1eba9c 100644
--- a/apps/server/src/services/llm/embeddings/storage.ts
+++ b/apps/server/src/services/llm/embeddings/storage.ts
@@ -11,7 +11,7 @@ import { SEARCH_CONSTANTS } from '../constants/search_constants.js';
 import type { NoteEmbeddingContext } from "./embeddings_interface.js";
 import becca from "../../../becca/becca.js";
 import { isNoteExcludedFromAIById } from "../utils/ai_exclusion_utils.js";
-import { getEmbeddingProviderPrecedence } from '../config/configuration_helpers.js';
+import { getSelectedEmbeddingProvider } from '../config/configuration_helpers.js';
 
 interface Similarity {
     noteId: string;
@@ -277,9 +277,10 @@ export async function findSimilarNotes(
                         log.info('No embeddings found for specified provider, trying fallback providers...');
 
                         // Use the new configuration system - no string parsing!
-                        const preferredProviders = await getEmbeddingProviderPrecedence();
+                        const selectedProvider = await getSelectedEmbeddingProvider();
+                        const preferredProviders = selectedProvider ? [selectedProvider] : [];
 
-                        log.info(`Using provider precedence: ${preferredProviders.join(', ')}`);
+                        log.info(`Using selected provider: ${selectedProvider || 'none'}`);
 
                         // Try providers in precedence order
                         for (const provider of preferredProviders) {
diff --git a/apps/server/src/services/llm/index_service.ts b/apps/server/src/services/llm/index_service.ts
index f1182495d..6887fbc36 100644
--- a/apps/server/src/services/llm/index_service.ts
+++ b/apps/server/src/services/llm/index_service.ts
@@ -12,6 +12,7 @@
 import log from "../log.js";
 import options from "../options.js";
 import becca from "../../becca/becca.js";
+import beccaLoader from "../../becca/becca_loader.js";
 import vectorStore from "./embeddings/index.js";
 import providerManager from "./providers/providers.js";
 import { ContextExtractor } from "./context/index.js";
@@ -21,6 +22,7 @@ import sqlInit from "../sql_init.js";
 import { CONTEXT_PROMPTS } from './constants/llm_prompt_constants.js';
 import { SEARCH_CONSTANTS } from './constants/search_constants.js';
 import { isNoteExcludedFromAI } from "./utils/ai_exclusion_utils.js";
+import { hasWorkingEmbeddingProviders } from "./provider_validation.js";
 
 export class IndexService {
     private initialized = false;
@@ -46,47 +48,16 @@ export class IndexService {
     async initialize() {
         if (this.initialized) return;
 
-        try {
-            // Check if database is initialized before proceeding
-            if (!sqlInit.isDbInitialized()) {
-                log.info("Index service: Database not initialized yet, skipping initialization");
-                return;
-            }
+        // Setup event listeners for note changes
+        this.setupEventListeners();
 
-            const aiEnabled = options.getOptionOrNull('aiEnabled') === "true";
-            if (!aiEnabled) {
-                log.info("Index service: AI features disabled, skipping initialization");
-                return;
-            }
-
-            // Check if embedding system is ready
-            const providers = await providerManager.getEnabledEmbeddingProviders();
-            if (!providers || providers.length === 0) {
-                throw new Error("No embedding providers available");
-            }
-
-            // Check if this instance should process embeddings
-            const embeddingLocation = await options.getOption('embeddingGenerationLocation') || 'client';
-            const isSyncServer = await this.isSyncServerForEmbeddings();
-            const shouldProcessEmbeddings = embeddingLocation === 'client' || isSyncServer;
-
-            // Setup automatic indexing if enabled and this instance should process embeddings
-            if (await options.getOptionBool('embeddingAutoUpdateEnabled') && shouldProcessEmbeddings) {
-                this.setupAutomaticIndexing();
-                log.info(`Index service: Automatic indexing enabled, processing embeddings ${isSyncServer ? 'as sync server' : 'as client'}`);
-            } else if (await options.getOptionBool('embeddingAutoUpdateEnabled')) {
-                log.info("Index service: Automatic indexing enabled, but this instance is not configured to process embeddings");
-            }
-
-            // Listen for note changes to update index
-            this.setupEventListeners();
-
-            this.initialized = true;
-            log.info("Index service initialized successfully");
-        } catch (error: any) {
-            log.error(`Error initializing index service: ${error.message || "Unknown error"}`);
-            throw error;
+        // Setup automatic indexing if enabled
+        if (await options.getOptionBool('embeddingAutoUpdateEnabled')) {
+            this.setupAutomaticIndexing();
         }
+
+        this.initialized = true;
+        log.info("Index service initialized");
     }
 
     /**
@@ -139,23 +110,7 @@ export class IndexService {
         this.automaticIndexingInterval = setInterval(async () => {
             try {
                 if (!this.indexingInProgress) {
-                    // Check if this instance should process embeddings
-                    const embeddingLocation = await options.getOption('embeddingGenerationLocation') || 'client';
-                    const isSyncServer = await this.isSyncServerForEmbeddings();
-                    const shouldProcessEmbeddings = embeddingLocation === 'client' || isSyncServer;
-
-                    if (!shouldProcessEmbeddings) {
-                        // This instance is not configured to process embeddings
-                        return;
-                    }
-
-                    const stats = await vectorStore.getEmbeddingStats();
-
-                    // Only run automatic indexing if we're below 95% completion
-                    if (stats.percentComplete < 95) {
-                        log.info(`Starting automatic indexing (current completion: ${stats.percentComplete}%)`);
-                        await this.runBatchIndexing(50); // Process 50 notes at a time
-                    }
+                    await this.runBatchIndexing(50); // Processing logic handles sync server checks
                 }
             } catch (error: any) {
                 log.error(`Error in automatic indexing: ${error.message || "Unknown error"}`);
@@ -265,7 +220,7 @@ export class IndexService {
                 this.indexRebuildTotal = totalNotes;
 
                 log.info("No embeddings found, starting full embedding generation first");
-                await vectorStore.reprocessAllNotes();
+                await this.reprocessAllNotes();
                 log.info("Full embedding generation initiated");
             } else {
                 // For index rebuild, use the number of embeddings as the total
@@ -292,7 +247,7 @@ export class IndexService {
                     // Only start indexing if we're below 90% completion or if embeddings exist but need optimization
                     if (stats.percentComplete < 90) {
                         log.info("Embedding coverage below 90%, starting full embedding generation");
-                        await vectorStore.reprocessAllNotes();
+                        await this.reprocessAllNotes();
                         log.info("Full embedding generation initiated");
                     } else {
                         log.info(`Embedding coverage at ${stats.percentComplete}%, starting index optimization`);
@@ -378,11 +333,10 @@ export class IndexService {
 
             if (!shouldProcessEmbeddings) {
                 // This instance is not configured to process embeddings
-                log.info("Skipping batch indexing as this instance is not configured to process embeddings");
                 return false;
             }
 
-            // Process the embedding queue
+            // Process the embedding queue (batch size is controlled by embeddingBatchSize option)
             await vectorStore.processEmbeddingQueue();
 
             return true;
@@ -491,51 +445,14 @@ export class IndexService {
         }
 
         try {
-            // Get all enabled embedding providers
-            const providers = await providerManager.getEnabledEmbeddingProviders();
-            if (!providers || providers.length === 0) {
-                throw new Error("No embedding providers available");
-            }
-
-            // Get the embedding provider precedence
-            const options = (await import('../options.js')).default;
-            let preferredProviders: string[] = [];
-
-            const embeddingPrecedence = await options.getOption('embeddingProviderPrecedence');
-            let provider;
-
-            if (embeddingPrecedence) {
-                // Parse the precedence string
-                if (embeddingPrecedence.startsWith('[') && embeddingPrecedence.endsWith(']')) {
-                    preferredProviders = JSON.parse(embeddingPrecedence);
-                } else if (typeof embeddingPrecedence === 'string') {
-                    if (embeddingPrecedence.includes(',')) {
-                        preferredProviders = embeddingPrecedence.split(',').map(p => p.trim());
-                    } else {
-                        preferredProviders = [embeddingPrecedence];
-                    }
-                }
-
-                // Find first enabled provider by precedence order
-                for (const providerName of preferredProviders) {
-                    const matchedProvider = providers.find(p => p.name === providerName);
-                    if (matchedProvider) {
-                        provider = matchedProvider;
-                        break;
-                    }
-                }
-
-                // If no match found, use first available
-                if (!provider && providers.length > 0) {
-                    provider = providers[0];
-                }
-            } else {
-                // Default to first available provider
-                provider = providers[0];
-            }
+            // Get the selected embedding provider on-demand
+            const selectedEmbeddingProvider = await options.getOption('embeddingSelectedProvider');
+            const provider = selectedEmbeddingProvider
+                ? await providerManager.getOrCreateEmbeddingProvider(selectedEmbeddingProvider)
+                : (await providerManager.getEnabledEmbeddingProviders())[0];
 
             if (!provider) {
-                throw new Error("No suitable embedding provider found");
+                throw new Error("No embedding provider available");
             }
 
             log.info(`Searching with embedding provider: ${provider.name}, model: ${provider.getConfig().model}`);
@@ -693,6 +610,12 @@ export class IndexService {
         }
 
         try {
+            // Get embedding providers on-demand
+            const providers = await providerManager.getEnabledEmbeddingProviders();
+            if (providers.length === 0) {
+                return "I don't have access to your note embeddings. Please configure an embedding provider in your AI settings.";
+            }
+
             // Find similar notes to the query
             const similarNotes = await this.findSimilarNotes(
                 query,
@@ -828,9 +751,13 @@ export class IndexService {
             // Get complete note context for indexing
             const context = await vectorStore.getNoteEmbeddingContext(noteId);
 
-            // Queue note for embedding with all available providers
-            const providers = await providerManager.getEnabledEmbeddingProviders();
-            for (const provider of providers) {
+            // Generate embedding with the selected provider
+            const selectedEmbeddingProvider = await options.getOption('embeddingSelectedProvider');
+            const provider = selectedEmbeddingProvider
+                ? await providerManager.getOrCreateEmbeddingProvider(selectedEmbeddingProvider)
+                : (await providerManager.getEnabledEmbeddingProviders())[0];
+
+            if (provider) {
                 try {
                     const embedding = await provider.generateNoteEmbeddings(context);
                     if (embedding) {
@@ -853,6 +780,189 @@ export class IndexService {
             return false;
         }
     }
+
+    /**
+     * Start embedding generation (called when AI is enabled)
+     */
+    async startEmbeddingGeneration() {
+        try {
+            log.info("Starting embedding generation system");
+
+            const aiEnabled = options.getOptionOrNull('aiEnabled') === "true";
+            if (!aiEnabled) {
+                log.error("Cannot start embedding generation - AI features are disabled");
+                throw new Error("AI features must be enabled first");
+            }
+
+            // Re-initialize if needed
+            if (!this.initialized) {
+                await this.initialize();
+            }
+
+            // Check if this instance should process embeddings
+            const embeddingLocation = await options.getOption('embeddingGenerationLocation') || 'client';
+            const isSyncServer = await this.isSyncServerForEmbeddings();
+            const shouldProcessEmbeddings = embeddingLocation === 'client' || isSyncServer;
+
+            if (!shouldProcessEmbeddings) {
+                log.info("This instance is not configured to process embeddings");
+                return;
+            }
+
+            // Get embedding providers (will be created on-demand when needed)
+            const providers = await providerManager.getEnabledEmbeddingProviders();
+            if (providers.length === 0) {
+                log.info("No embedding providers configured, but continuing initialization");
+            } else {
+                log.info(`Found ${providers.length} embedding providers: ${providers.map(p => p.name).join(', ')}`);
+            }
+
+            // Setup automatic indexing if enabled
+            if (await options.getOptionBool('embeddingAutoUpdateEnabled')) {
+                this.setupAutomaticIndexing();
+                log.info(`Automatic embedding indexing started ${isSyncServer ? 'as sync server' : 'as client'}`);
+            }
+
+            // Start background processing of the embedding queue
+            const { setupEmbeddingBackgroundProcessing } = await import('./embeddings/events.js');
+            await setupEmbeddingBackgroundProcessing();
+
+            // Re-initialize event listeners
+            this.setupEventListeners();
+
+            // Queue notes that don't have embeddings for current providers
+            await this.queueNotesForMissingEmbeddings();
+
+            // Start processing the queue immediately
+            await this.runBatchIndexing(20);
+
+            log.info("Embedding generation started successfully");
+        } catch (error: any) {
+            log.error(`Error starting embedding generation: ${error.message || "Unknown error"}`);
+            throw error;
+        }
+    }
+
+
+
+    /**
+     * Queue notes that don't have embeddings for current provider settings
+     */
+    async queueNotesForMissingEmbeddings() {
+        try {
+            // Wait for becca to be fully loaded before accessing notes
+            await beccaLoader.beccaLoaded;
+
+            // Get all non-deleted notes
+            const allNotes = Object.values(becca.notes).filter(note => !note.isDeleted);
+
+            // Get enabled providers
+            const providers = await providerManager.getEnabledEmbeddingProviders();
+            if (providers.length === 0) {
+                return;
+            }
+
+            let queuedCount = 0;
+            let excludedCount = 0;
+
+            // Process notes in batches to avoid overwhelming the system
+            const batchSize = 100;
+            for (let i = 0; i < allNotes.length; i += batchSize) {
+                const batch = allNotes.slice(i, i + batchSize);
+
+                for (const note of batch) {
+                    try {
+                        // Skip notes excluded from AI
+                        if (isNoteExcludedFromAI(note)) {
+                            excludedCount++;
+                            continue;
+                        }
+
+                        // Check if note needs embeddings for any enabled provider
+                        let needsEmbedding = false;
+
+                        for (const provider of providers) {
+                            const config = provider.getConfig();
+                            const existingEmbedding = await vectorStore.getEmbeddingForNote(
+                                note.noteId,
+                                provider.name,
+                                config.model
+                            );
+
+                            if (!existingEmbedding) {
+                                needsEmbedding = true;
+                                break;
+                            }
+                        }
+
+                        if (needsEmbedding) {
+                            await vectorStore.queueNoteForEmbedding(note.noteId, 'UPDATE');
+                            queuedCount++;
+                        }
+                    } catch (error: any) {
+                        log.error(`Error checking embeddings for note ${note.noteId}: ${error.message || 'Unknown error'}`);
+                    }
+                }
+
+            }
+        } catch (error: any) {
+            log.error(`Error queuing notes for missing embeddings: ${error.message || 'Unknown error'}`);
+        }
+    }
+
+    /**
+     * Reprocess all notes to update embeddings
+     */
+    async reprocessAllNotes() {
+        if (!this.initialized) {
+            await this.initialize();
+        }
+
+        try {
+            // Get all non-deleted note IDs
+            const noteIds = await sql.getColumn("SELECT noteId FROM notes WHERE isDeleted = 0");
+
+            // Process each note ID
+            for (const noteId of noteIds) {
+                await vectorStore.queueNoteForEmbedding(noteId as string, 'UPDATE');
+            }
+        } catch (error: any) {
+            log.error(`Error reprocessing all notes: ${error.message || 'Unknown error'}`);
+            throw error;
+        }
+    }
+
+    /**
+     * Stop embedding generation (called when AI is disabled)
+     */
+    async stopEmbeddingGeneration() {
+        try {
+            log.info("Stopping embedding generation system");
+
+            // Clear automatic indexing interval
+            if (this.automaticIndexingInterval) {
+                clearInterval(this.automaticIndexingInterval);
+                this.automaticIndexingInterval = undefined;
+                log.info("Automatic indexing stopped");
+            }
+
+            // Stop the background processing from embeddings/events.ts
+            const { stopEmbeddingBackgroundProcessing } = await import('./embeddings/events.js');
+            stopEmbeddingBackgroundProcessing();
+
+            // Clear all embedding providers to clean up resources
+            providerManager.clearAllEmbeddingProviders();
+
+            // Mark as not indexing
+            this.indexingInProgress = false;
+            this.indexRebuildInProgress = false;
+
+            log.info("Embedding generation stopped successfully");
+        } catch (error: any) {
+            log.error(`Error stopping embedding generation: ${error.message || "Unknown error"}`);
+            throw error;
+        }
+    }
 }
 
 // Create singleton instance
diff --git a/apps/server/src/services/llm/interfaces/ai_service_interfaces.ts b/apps/server/src/services/llm/interfaces/ai_service_interfaces.ts
index 3126691a4..52736cbd5 100644
--- a/apps/server/src/services/llm/interfaces/ai_service_interfaces.ts
+++ b/apps/server/src/services/llm/interfaces/ai_service_interfaces.ts
@@ -28,9 +28,9 @@ export interface AIServiceManagerConfig {
  * Interface for managing AI service providers
  */
 export interface IAIServiceManager {
-  getService(provider?: string): AIService;
+  getService(provider?: string): Promise;
   getAvailableProviders(): string[];
-  getPreferredProvider(): string;
+  getSelectedProvider(): string;
   isProviderAvailable(provider: string): boolean;
   getProviderMetadata(provider: string): ProviderMetadata | null;
   getAIEnabled(): boolean;
diff --git a/apps/server/src/services/llm/interfaces/configuration_interfaces.ts b/apps/server/src/services/llm/interfaces/configuration_interfaces.ts
index 5a03dc4f1..6adcac977 100644
--- a/apps/server/src/services/llm/interfaces/configuration_interfaces.ts
+++ b/apps/server/src/services/llm/interfaces/configuration_interfaces.ts
@@ -46,8 +46,8 @@ export interface ModelCapabilities {
  */
 export interface AIConfig {
     enabled: boolean;
-    providerPrecedence: ProviderPrecedenceConfig;
-    embeddingProviderPrecedence: EmbeddingProviderPrecedenceConfig;
+    selectedProvider: ProviderType | null;
+    selectedEmbeddingProvider: EmbeddingProviderType | null;
     defaultModels: Record;
     providerSettings: ProviderSettings;
 }
@@ -87,7 +87,7 @@ export type ProviderType = 'openai' | 'anthropic' | 'ollama';
 /**
  * Valid embedding provider types
  */
-export type EmbeddingProviderType = 'openai' | 'ollama' | 'local';
+export type EmbeddingProviderType = 'openai' | 'voyage' | 'ollama' | 'local';
 
 /**
  * Model identifier with provider prefix (e.g., "openai:gpt-4" or "ollama:llama2")
diff --git a/apps/server/src/services/llm/pipeline/chat_pipeline.ts b/apps/server/src/services/llm/pipeline/chat_pipeline.ts
index 947a562e6..50671a809 100644
--- a/apps/server/src/services/llm/pipeline/chat_pipeline.ts
+++ b/apps/server/src/services/llm/pipeline/chat_pipeline.ts
@@ -298,6 +298,9 @@ export class ChatPipeline {
             this.updateStageMetrics('llmCompletion', llmStartTime);
             log.info(`Received LLM response from model: ${completion.response.model}, provider: ${completion.response.provider}`);
 
+            // Track whether content has been streamed to prevent duplication
+            let hasStreamedContent = false;
+
             // Handle streaming if enabled and available
             // Use shouldEnableStream variable which contains our streaming decision
             if (shouldEnableStream && completion.response.stream && streamCallback) {
@@ -311,6 +314,9 @@ export class ChatPipeline {
 
                     // Forward to callback with original chunk data in case it contains additional information
                     streamCallback(processedChunk.text, processedChunk.done, chunk);
+                    
+                    // Mark that we have streamed content to prevent duplication
+                    hasStreamedContent = true;
                 });
             }
 
@@ -767,11 +773,15 @@ export class ChatPipeline {
                     const responseText = currentResponse.text || "";
                     log.info(`Resuming streaming with final response: ${responseText.length} chars`);
 
-                    if (responseText.length > 0) {
-                        // Resume streaming with the final response text
+                    if (responseText.length > 0 && !hasStreamedContent) {
+                        // Resume streaming with the final response text only if we haven't already streamed content
                         // This is where we send the definitive done:true signal with the complete content
                         streamCallback(responseText, true);
                         log.info(`Sent final response with done=true signal and text content`);
+                    } else if (hasStreamedContent) {
+                        log.info(`Content already streamed, sending done=true signal only after tool execution`);
+                        // Just send the done signal without duplicating content
+                        streamCallback('', true);
                     } else {
                         // For Anthropic, sometimes text is empty but response is in stream
                         if ((currentResponse.provider === 'Anthropic' || currentResponse.provider === 'OpenAI') && currentResponse.stream) {
@@ -803,13 +813,17 @@ export class ChatPipeline {
                 log.info(`LLM response did not contain any tool calls, skipping tool execution`);
 
                 // Handle streaming for responses without tool calls
-                if (shouldEnableStream && streamCallback) {
+                if (shouldEnableStream && streamCallback && !hasStreamedContent) {
                     log.info(`Sending final streaming response without tool calls: ${currentResponse.text.length} chars`);
 
                     // Send the final response with done=true to complete the streaming
                     streamCallback(currentResponse.text, true);
 
                     log.info(`Sent final non-tool response with done=true signal`);
+                } else if (shouldEnableStream && streamCallback && hasStreamedContent) {
+                    log.info(`Content already streamed, sending done=true signal only`);
+                    // Just send the done signal without duplicating content
+                    streamCallback('', true);
                 }
             }
 
diff --git a/apps/server/src/services/llm/pipeline/stages/context_extraction_stage.ts b/apps/server/src/services/llm/pipeline/stages/context_extraction_stage.ts
index 95d7620e2..b1eaa69f9 100644
--- a/apps/server/src/services/llm/pipeline/stages/context_extraction_stage.ts
+++ b/apps/server/src/services/llm/pipeline/stages/context_extraction_stage.ts
@@ -43,7 +43,7 @@ export class ContextExtractionStage {
 
             // Get enhanced context from the context service
             const contextService = aiServiceManager.getContextService();
-            const llmService = aiServiceManager.getService();
+            const llmService = await aiServiceManager.getService();
 
             if (contextService) {
                 // Use unified context service to get smart context
diff --git a/apps/server/src/services/llm/pipeline/stages/llm_completion_stage.ts b/apps/server/src/services/llm/pipeline/stages/llm_completion_stage.ts
index 7dd6984c8..6354e4c59 100644
--- a/apps/server/src/services/llm/pipeline/stages/llm_completion_stage.ts
+++ b/apps/server/src/services/llm/pipeline/stages/llm_completion_stage.ts
@@ -104,7 +104,7 @@ export class LLMCompletionStage extends BasePipelineStage SEARCH_CONSTANTS.CONTEXT.CONTENT_LENGTH.HIGH_THRESHOLD ? 'high' : 'medium';
             }
 
-            // Set the model and add provider metadata
-            updatedOptions.model = modelName;
-            this.addProviderMetadata(updatedOptions, preferredProvider as ServiceProviders, modelName);
+            // Add provider metadata (model is already set above)
+            this.addProviderMetadata(updatedOptions, selectedProvider as ServiceProviders, updatedOptions.model);
 
-            log.info(`Selected model: ${modelName} from provider: ${preferredProvider} for query complexity: ${queryComplexity}`);
+            log.info(`Selected model: ${updatedOptions.model} from provider: ${selectedProvider} for query complexity: ${queryComplexity}`);
             log.info(`[ModelSelectionStage] Final options: ${JSON.stringify({
                 model: updatedOptions.model,
                 stream: updatedOptions.stream,
-                provider: preferredProvider,
+                provider: selectedProvider,
                 enableTools: updatedOptions.enableTools
             })}`);
 
@@ -210,39 +219,41 @@ export class ModelSelectionStage extends BasePipelineStage {
         try {
-            // Use the new configuration system
-            const providers = await getProviderPrecedence();
+            // Use the same logic as the main process method
+            const { getValidModelConfig, getSelectedProvider } = await import('../../config/configuration_helpers.js');
+            const selectedProvider = await getSelectedProvider();
 
-            // Use only providers that are available
-            const availableProviders = providers.filter(provider =>
-                aiServiceManager.isProviderAvailable(provider));
-
-            if (availableProviders.length === 0) {
-                throw new Error('No AI providers are available');
+            if (!selectedProvider) {
+                throw new Error('No AI provider is selected. Please select a provider in your AI settings.');
             }
 
-            // Get the first available provider and its default model
-            const defaultProvider = availableProviders[0];
-            const defaultModel = await getDefaultModelForProvider(defaultProvider);
+            // Check if the provider is available through the service manager
+            if (!aiServiceManager.isProviderAvailable(selectedProvider)) {
+                throw new Error(`Selected provider ${selectedProvider} is not available`);
+            }
 
-            if (!defaultModel) {
-                throw new Error(`No default model configured for provider ${defaultProvider}. Please configure a default model in your AI settings.`);
+            // Try to get a valid model config
+            const modelConfig = await getValidModelConfig(selectedProvider);
+            
+            if (!modelConfig) {
+                throw new Error(`No default model configured for provider ${selectedProvider}. Please configure a default model in your AI settings.`);
             }
 
             // Set provider metadata
             if (!input.options.providerMetadata) {
                 input.options.providerMetadata = {
-                    provider: defaultProvider as 'openai' | 'anthropic' | 'ollama' | 'local',
-                    modelId: defaultModel
+                    provider: selectedProvider as 'openai' | 'anthropic' | 'ollama' | 'local',
+                    modelId: modelConfig.model
                 };
             }
 
-            log.info(`Selected default model ${defaultModel} from provider ${defaultProvider}`);
-            return defaultModel;
+            log.info(`Selected default model ${modelConfig.model} from provider ${selectedProvider}`);
+            return modelConfig.model;
         } catch (error) {
             log.error(`Error determining default model: ${error}`);
             throw error; // Don't provide fallback defaults, let the error propagate
@@ -271,4 +282,49 @@ export class ModelSelectionStage extends BasePipelineStage {
+        try {
+            log.info(`Getting default model for provider ${provider} using AI service manager`);
+            
+            // Use the existing AI service manager instead of duplicating API calls
+            const service = await aiServiceManager.getInstance().getService(provider);
+            
+            if (!service || !service.isAvailable()) {
+                log.info(`Provider ${provider} service is not available`);
+                return null;
+            }
+
+            // Check if the service has a method to get available models
+            if (typeof (service as any).getAvailableModels === 'function') {
+                try {
+                    const models = await (service as any).getAvailableModels();
+                    if (models && models.length > 0) {
+                        // Use the first available model - no hardcoded preferences
+                        const selectedModel = models[0];
+                        
+                        // Import server-side options to update the default model
+                        const optionService = (await import('../../../options.js')).default;
+                        const optionKey = `${provider}DefaultModel` as const;
+                        
+                        await optionService.setOption(optionKey, selectedModel);
+                        log.info(`Set default ${provider} model to: ${selectedModel}`);
+                        return selectedModel;
+                    }
+                } catch (modelError) {
+                    log.error(`Error fetching models from ${provider} service: ${modelError}`);
+                }
+            }
+            
+            log.info(`Provider ${provider} does not support dynamic model fetching`);
+            return null;
+        } catch (error) {
+            log.error(`Error getting default model for provider ${provider}: ${error}`);
+            return null;
+        }
+    }
 }
diff --git a/apps/server/src/services/llm/pipeline/stages/semantic_context_extraction_stage.ts b/apps/server/src/services/llm/pipeline/stages/semantic_context_extraction_stage.ts
index bf2cc8fd7..139510663 100644
--- a/apps/server/src/services/llm/pipeline/stages/semantic_context_extraction_stage.ts
+++ b/apps/server/src/services/llm/pipeline/stages/semantic_context_extraction_stage.ts
@@ -50,7 +50,7 @@ export class SemanticContextExtractionStage extends BasePipelineStage {
+    const result: ProviderValidationResult = {
+        hasValidProviders: false,
+        validEmbeddingProviders: [],
+        validChatProviders: [],
+        errors: [],
+        warnings: []
+    };
+
+    try {
+        // Check if AI is enabled
+        const aiEnabled = await options.getOptionBool('aiEnabled');
+        if (!aiEnabled) {
+            result.warnings.push("AI features are disabled");
+            return result;
+        }
+
+        // Check configuration only - don't create providers
+        await checkEmbeddingProviderConfigs(result);
+        await checkChatProviderConfigs(result);
+
+        // Determine if we have any valid providers based on configuration
+        result.hasValidProviders = result.validChatProviders.length > 0;
+
+        if (!result.hasValidProviders) {
+            result.errors.push("No valid AI providers are configured");
+        }
+
+    } catch (error: any) {
+        result.errors.push(`Error during provider validation: ${error.message || 'Unknown error'}`);
+    }
+
+    return result;
+}
+
+/**
+ * Check embedding provider configurations without creating providers
+ */
+async function checkEmbeddingProviderConfigs(result: ProviderValidationResult): Promise {
+    try {
+        // Check OpenAI embedding configuration
+        const openaiApiKey = await options.getOption('openaiApiKey');
+        const openaiBaseUrl = await options.getOption('openaiBaseUrl');
+        if (openaiApiKey || openaiBaseUrl) {
+            if (!openaiApiKey) {
+                result.warnings.push("OpenAI embedding: No API key (may work with compatible endpoints)");
+            }
+            log.info("OpenAI embedding provider configuration available");
+        }
+
+        // Check Ollama embedding configuration
+        const ollamaEmbeddingBaseUrl = await options.getOption('ollamaEmbeddingBaseUrl');
+        if (ollamaEmbeddingBaseUrl) {
+            log.info("Ollama embedding provider configuration available");
+        }
+
+        // Check Voyage embedding configuration
+        const voyageApiKey = await options.getOption('voyageApiKey' as any);
+        if (voyageApiKey) {
+            log.info("Voyage embedding provider configuration available");
+        }
+
+        // Local provider is always available
+        log.info("Local embedding provider available as fallback");
+
+    } catch (error: any) {
+        result.errors.push(`Error checking embedding provider configs: ${error.message || 'Unknown error'}`);
+    }
+}
+
+/**
+ * Check chat provider configurations without creating providers
+ */
+async function checkChatProviderConfigs(result: ProviderValidationResult): Promise {
+    try {
+        // Check OpenAI chat provider
+        const openaiApiKey = await options.getOption('openaiApiKey');
+        const openaiBaseUrl = await options.getOption('openaiBaseUrl');
+        
+        if (openaiApiKey || openaiBaseUrl) {
+            if (!openaiApiKey) {
+                result.warnings.push("OpenAI chat: No API key (may work with compatible endpoints)");
+            }
+            result.validChatProviders.push('openai');
+        }
+
+        // Check Anthropic chat provider
+        const anthropicApiKey = await options.getOption('anthropicApiKey');
+        if (anthropicApiKey) {
+            result.validChatProviders.push('anthropic');
+        }
+
+        // Check Ollama chat provider
+        const ollamaBaseUrl = await options.getOption('ollamaBaseUrl');
+        if (ollamaBaseUrl) {
+            result.validChatProviders.push('ollama');
+        }
+
+        if (result.validChatProviders.length === 0) {
+            result.warnings.push("No chat providers configured. Please configure at least one provider.");
+        }
+
+    } catch (error: any) {
+        result.errors.push(`Error checking chat provider configs: ${error.message || 'Unknown error'}`);
+    }
+}
+
+
+/**
+ * Check if any chat providers are configured
+ */
+export async function hasWorkingChatProviders(): Promise {
+    const validation = await validateProviders();
+    return validation.validChatProviders.length > 0;
+}
+
+/**
+ * Check if any embedding providers are configured (simplified)
+ */
+export async function hasWorkingEmbeddingProviders(): Promise {
+    if (!(await options.getOptionBool('aiEnabled'))) {
+        return false;
+    }
+    
+    // Check if any embedding provider is configured
+    const openaiKey = await options.getOption('openaiApiKey');
+    const openaiBaseUrl = await options.getOption('openaiBaseUrl');
+    const ollamaUrl = await options.getOption('ollamaEmbeddingBaseUrl');
+    const voyageKey = await options.getOption('voyageApiKey' as any);
+    
+    // Local provider is always available as fallback
+    return !!(openaiKey || openaiBaseUrl || ollamaUrl || voyageKey) || true;
+}
+
+/**
+ * Log validation results in a user-friendly way
+ */
+export function logValidationResults(validation: ProviderValidationResult): void {
+    if (validation.hasValidProviders) {
+        log.info(`AI provider validation passed: ${validation.validEmbeddingProviders.length} embedding providers, ${validation.validChatProviders.length} chat providers`);
+        
+        if (validation.validEmbeddingProviders.length > 0) {
+            log.info(`Working embedding providers: ${validation.validEmbeddingProviders.map(p => p.name).join(', ')}`);
+        }
+        
+        if (validation.validChatProviders.length > 0) {
+            log.info(`Working chat providers: ${validation.validChatProviders.join(', ')}`);
+        }
+    } else {
+        log.info("AI provider validation failed: No working providers found");
+    }
+
+    validation.warnings.forEach(warning => log.info(`Provider validation: ${warning}`));
+    validation.errors.forEach(error => log.error(`Provider validation: ${error}`));
+}
\ No newline at end of file
diff --git a/apps/server/src/services/llm/providers/anthropic_service.ts b/apps/server/src/services/llm/providers/anthropic_service.ts
index a533acf4a..ed034bdfd 100644
--- a/apps/server/src/services/llm/providers/anthropic_service.ts
+++ b/apps/server/src/services/llm/providers/anthropic_service.ts
@@ -606,4 +606,12 @@ export class AnthropicService extends BaseAIService {
 
         return convertedTools;
     }
+
+    /**
+     * Clear cached Anthropic client to force recreation with new settings
+     */
+    clearCache(): void {
+        this.client = null;
+        log.info('Anthropic client cache cleared');
+    }
 }
diff --git a/apps/server/src/services/llm/providers/ollama_service.ts b/apps/server/src/services/llm/providers/ollama_service.ts
index 750118027..4ebbbaa4b 100644
--- a/apps/server/src/services/llm/providers/ollama_service.ts
+++ b/apps/server/src/services/llm/providers/ollama_service.ts
@@ -526,4 +526,13 @@ export class OllamaService extends BaseAIService {
         log.info(`Added tool execution feedback: ${toolExecutionStatus.length} statuses`);
         return updatedMessages;
     }
+
+    /**
+     * Clear cached Ollama client to force recreation with new settings
+     */
+    clearCache(): void {
+        // Ollama service doesn't maintain a persistent client like OpenAI/Anthropic
+        // but we can clear any future cached state here if needed
+        log.info('Ollama client cache cleared (no persistent client to clear)');
+    }
 }
diff --git a/apps/server/src/services/llm/providers/openai_service.ts b/apps/server/src/services/llm/providers/openai_service.ts
index e0633ca1f..411f512f7 100644
--- a/apps/server/src/services/llm/providers/openai_service.ts
+++ b/apps/server/src/services/llm/providers/openai_service.ts
@@ -14,7 +14,9 @@ export class OpenAIService extends BaseAIService {
     }
 
     override isAvailable(): boolean {
-        return super.isAvailable() && !!options.getOption('openaiApiKey');
+        // Make API key optional to support OpenAI-compatible endpoints that don't require authentication
+        // The provider is considered available as long as the parent checks pass
+        return super.isAvailable();
     }
 
     private getClient(apiKey: string, baseUrl?: string): OpenAI {
@@ -29,7 +31,7 @@ export class OpenAIService extends BaseAIService {
 
     async generateChatCompletion(messages: Message[], opts: ChatCompletionOptions = {}): Promise {
         if (!this.isAvailable()) {
-            throw new Error('OpenAI service is not available. Check API key and AI settings.');
+            throw new Error('OpenAI service is not available. Check AI settings.');
         }
 
         // Get provider-specific options from the central provider manager
@@ -257,4 +259,12 @@ export class OpenAIService extends BaseAIService {
             throw error;
         }
     }
+
+    /**
+     * Clear cached OpenAI client to force recreation with new settings
+     */
+    clearCache(): void {
+        this.openai = null;
+        log.info('OpenAI client cache cleared');
+    }
 }
diff --git a/apps/server/src/services/llm/providers/providers.ts b/apps/server/src/services/llm/providers/providers.ts
index f4d69801c..dae8b34a0 100644
--- a/apps/server/src/services/llm/providers/providers.ts
+++ b/apps/server/src/services/llm/providers/providers.ts
@@ -86,6 +86,29 @@ export function registerEmbeddingProvider(provider: EmbeddingProvider) {
     log.info(`Registered embedding provider: ${provider.name}`);
 }
 
+/**
+ * Unregister an embedding provider
+ */
+export function unregisterEmbeddingProvider(name: string): boolean {
+    const existed = providers.has(name);
+    if (existed) {
+        providers.delete(name);
+        log.info(`Unregistered embedding provider: ${name}`);
+    }
+    return existed;
+}
+
+/**
+ * Clear all embedding providers
+ */
+export function clearAllEmbeddingProviders(): void {
+    const providerNames = Array.from(providers.keys());
+    providers.clear();
+    if (providerNames.length > 0) {
+        log.info(`Cleared all embedding providers: ${providerNames.join(', ')}`);
+    }
+}
+
 /**
  * Get all registered embedding providers
  */
@@ -101,35 +124,126 @@ export function getEmbeddingProvider(name: string): EmbeddingProvider | undefine
 }
 
 /**
- * Get all enabled embedding providers
+ * Get or create a specific embedding provider with inline validation
  */
-export async function getEnabledEmbeddingProviders(): Promise {
+export async function getOrCreateEmbeddingProvider(providerName: string): Promise {
+    // Return existing provider if already created and valid
+    const existing = providers.get(providerName);
+    if (existing) {
+        return existing;
+    }
+
+    // Create and validate provider on-demand
+    try {
+        let provider: EmbeddingProvider | null = null;
+
+        switch (providerName) {
+            case 'ollama': {
+                const baseUrl = await options.getOption('ollamaEmbeddingBaseUrl');
+                if (!baseUrl) return null;
+
+                const model = await options.getOption('ollamaEmbeddingModel');
+                provider = new OllamaEmbeddingProvider({
+                    model,
+                    dimension: 768,
+                    type: 'float32',
+                    baseUrl
+                });
+
+                // Validate by initializing (if provider supports it)
+                if ('initialize' in provider && typeof provider.initialize === 'function') {
+                    await provider.initialize();
+                }
+                break;
+            }
+
+            case 'openai': {
+                const apiKey = await options.getOption('openaiApiKey');
+                const baseUrl = await options.getOption('openaiBaseUrl');
+                if (!apiKey && !baseUrl) return null;
+
+                const model = await options.getOption('openaiEmbeddingModel');
+                provider = new OpenAIEmbeddingProvider({
+                    model,
+                    dimension: 1536,
+                    type: 'float32',
+                    apiKey: apiKey || '',
+                    baseUrl: baseUrl || 'https://api.openai.com/v1'
+                });
+
+                if (!apiKey) {
+                    log.info('OpenAI embedding provider created without API key for compatible endpoints');
+                }
+                break;
+            }
+
+            case 'voyage': {
+                const apiKey = await options.getOption('voyageApiKey' as any);
+                if (!apiKey) return null;
+
+                const model = await options.getOption('voyageEmbeddingModel') || 'voyage-2';
+                provider = new VoyageEmbeddingProvider({
+                    model,
+                    dimension: 1024,
+                    type: 'float32',
+                    apiKey,
+                    baseUrl: 'https://api.voyageai.com/v1'
+                });
+                break;
+            }
+
+            case 'local': {
+                provider = new SimpleLocalEmbeddingProvider({
+                    model: 'local',
+                    dimension: 384,
+                    type: 'float32'
+                });
+                break;
+            }
+
+            default:
+                return null;
+        }
+
+        if (provider) {
+            registerEmbeddingProvider(provider);
+            log.info(`Created and validated ${providerName} embedding provider`);
+            return provider;
+        }
+    } catch (error: any) {
+        log.error(`Failed to create ${providerName} embedding provider: ${error.message || 'Unknown error'}`);
+    }
+
+    return null;
+}
+
+/**
+ * Get all enabled embedding providers for the specified feature
+ */
+export async function getEnabledEmbeddingProviders(feature: 'embeddings' | 'chat' = 'embeddings'): Promise {
     if (!(await options.getOptionBool('aiEnabled'))) {
         return [];
     }
 
-    // Get providers from database ordered by priority
-    const dbProviders = await sql.getRows(`
-        SELECT providerId, name, config
-        FROM embedding_providers
-        ORDER BY priority DESC`
-    );
-
     const result: EmbeddingProvider[] = [];
 
-    for (const row of dbProviders) {
-        const rowData = row as any;
-        const provider = providers.get(rowData.name);
+    // Get the selected provider for the feature
+    const selectedProvider = feature === 'embeddings'
+        ? await options.getOption('embeddingSelectedProvider')
+        : await options.getOption('aiSelectedProvider');
 
-        if (provider) {
-            result.push(provider);
-        } else {
-            // Only log error if we haven't logged it before for this provider
-            if (!loggedProviderErrors.has(rowData.name)) {
-                log.error(`Enabled embedding provider ${rowData.name} not found in registered providers`);
-                loggedProviderErrors.add(rowData.name);
-            }
+        // Try to get or create the specific selected provider
+        const provider = await getOrCreateEmbeddingProvider(selectedProvider);
+        if (!provider) {
+            throw new Error(`Failed to create selected embedding provider: ${selectedProvider}. Please check your configuration.`);
         }
+        result.push(provider);
+
+
+    // Always ensure local provider as fallback
+    const localProvider = await getOrCreateEmbeddingProvider('local');
+    if (localProvider && !result.some(p => p.name === 'local')) {
+        result.push(localProvider);
     }
 
     return result;
@@ -232,144 +346,18 @@ export async function getEmbeddingProviderConfigs() {
     return await sql.getRows("SELECT * FROM embedding_providers ORDER BY priority DESC");
 }
 
-/**
- * Initialize the default embedding providers
- */
-export async function initializeDefaultProviders() {
-    // Register built-in providers
-    try {
-        // Register OpenAI provider if API key is configured
-        const openaiApiKey = await options.getOption('openaiApiKey');
-        if (openaiApiKey) {
-            const openaiModel = await options.getOption('openaiEmbeddingModel') || 'text-embedding-3-small';
-            const openaiBaseUrl = await options.getOption('openaiBaseUrl') || 'https://api.openai.com/v1';
-
-            registerEmbeddingProvider(new OpenAIEmbeddingProvider({
-                model: openaiModel,
-                dimension: 1536, // OpenAI's typical dimension
-                type: 'float32',
-                apiKey: openaiApiKey,
-                baseUrl: openaiBaseUrl
-            }));
-
-            // Create OpenAI provider config if it doesn't exist
-            const existingOpenAI = await sql.getRow(
-                "SELECT * FROM embedding_providers WHERE name = ?",
-                ['openai']
-            );
-
-            if (!existingOpenAI) {
-                await createEmbeddingProviderConfig('openai', {
-                    model: openaiModel,
-                    dimension: 1536,
-                    type: 'float32'
-                }, 100);
-            }
-        }
-
-        // Register Voyage provider if API key is configured
-        const voyageApiKey = await options.getOption('voyageApiKey' as any);
-        if (voyageApiKey) {
-            const voyageModel = await options.getOption('voyageEmbeddingModel') || 'voyage-2';
-            const voyageBaseUrl = 'https://api.voyageai.com/v1';
-
-            registerEmbeddingProvider(new VoyageEmbeddingProvider({
-                model: voyageModel,
-                dimension: 1024, // Voyage's embedding dimension
-                type: 'float32',
-                apiKey: voyageApiKey,
-                baseUrl: voyageBaseUrl
-            }));
-
-            // Create Voyage provider config if it doesn't exist
-            const existingVoyage = await sql.getRow(
-                "SELECT * FROM embedding_providers WHERE name = ?",
-                ['voyage']
-            );
-
-            if (!existingVoyage) {
-                await createEmbeddingProviderConfig('voyage', {
-                    model: voyageModel,
-                    dimension: 1024,
-                    type: 'float32'
-                }, 75);
-            }
-        }
-
-        // Register Ollama provider if base URL is configured
-        const ollamaBaseUrl = await options.getOption('ollamaBaseUrl');
-        if (ollamaBaseUrl) {
-            // Use specific embedding models if available
-            const embeddingModel = await options.getOption('ollamaEmbeddingModel');
-
-            try {
-                // Create provider with initial dimension to be updated during initialization
-                const ollamaProvider = new OllamaEmbeddingProvider({
-                    model: embeddingModel,
-                    dimension: 768, // Initial value, will be updated during initialization
-                    type: 'float32',
-                    baseUrl: ollamaBaseUrl
-                });
-
-                // Register the provider
-                registerEmbeddingProvider(ollamaProvider);
-
-                // Initialize the provider to detect model capabilities
-                await ollamaProvider.initialize();
-
-                // Create Ollama provider config if it doesn't exist
-                const existingOllama = await sql.getRow(
-                    "SELECT * FROM embedding_providers WHERE name = ?",
-                    ['ollama']
-                );
-
-                if (!existingOllama) {
-                    await createEmbeddingProviderConfig('ollama', {
-                        model: embeddingModel,
-                        dimension: ollamaProvider.getDimension(),
-                        type: 'float32'
-                    }, 50);
-                }
-            } catch (error: any) {
-                log.error(`Error initializing Ollama embedding provider: ${error.message || 'Unknown error'}`);
-            }
-        }
-
-        // Always register local provider as fallback
-        registerEmbeddingProvider(new SimpleLocalEmbeddingProvider({
-            model: 'local',
-            dimension: 384,
-            type: 'float32'
-        }));
-
-        // Create local provider config if it doesn't exist
-        const existingLocal = await sql.getRow(
-            "SELECT * FROM embedding_providers WHERE name = ?",
-            ['local']
-        );
-
-        if (!existingLocal) {
-            await createEmbeddingProviderConfig('local', {
-                model: 'local',
-                dimension: 384,
-                type: 'float32'
-            }, 10);
-        }
-    } catch (error: any) {
-        log.error(`Error initializing default embedding providers: ${error.message || 'Unknown error'}`);
-    }
-}
-
 export default {
     registerEmbeddingProvider,
+    unregisterEmbeddingProvider,
+    clearAllEmbeddingProviders,
     getEmbeddingProviders,
     getEmbeddingProvider,
     getEnabledEmbeddingProviders,
+    getOrCreateEmbeddingProvider,
     createEmbeddingProviderConfig,
     updateEmbeddingProviderConfig,
     deleteEmbeddingProviderConfig,
-    getEmbeddingProviderConfigs,
-    initializeDefaultProviders
+    getEmbeddingProviderConfigs
 };
 
 /**
@@ -382,7 +370,8 @@ export function getOpenAIOptions(
     try {
         const apiKey = options.getOption('openaiApiKey');
         if (!apiKey) {
-            throw new Error('OpenAI API key is not configured');
+            // Log warning but don't throw - some OpenAI-compatible endpoints don't require API keys
+            log.info('OpenAI API key is not configured. This may cause issues with official OpenAI endpoints.');
         }
 
         const baseUrl = options.getOption('openaiBaseUrl') || PROVIDER_CONSTANTS.OPENAI.BASE_URL;
@@ -407,7 +396,7 @@ export function getOpenAIOptions(
 
         return {
             // Connection settings
-            apiKey,
+            apiKey: apiKey || '', // Default to empty string if no API key
             baseUrl,
 
             // Provider metadata
diff --git a/apps/server/src/services/llm/tools/note_summarization_tool.ts b/apps/server/src/services/llm/tools/note_summarization_tool.ts
index bc5999e0c..8fa5d39d8 100644
--- a/apps/server/src/services/llm/tools/note_summarization_tool.ts
+++ b/apps/server/src/services/llm/tools/note_summarization_tool.ts
@@ -102,12 +102,7 @@ export class NoteSummarizationTool implements ToolHandler {
             const cleanContent = this.cleanHtml(content);
 
             // Generate the summary using the AI service
-            const aiService = aiServiceManager.getService();
-
-            if (!aiService) {
-                log.error('No AI service available for summarization');
-                return `Error: No AI service is available for summarization`;
-            }
+            const aiService = await aiServiceManager.getService();
 
             log.info(`Using ${aiService.getName()} to generate summary`);
 
diff --git a/apps/server/src/services/llm/tools/relationship_tool.ts b/apps/server/src/services/llm/tools/relationship_tool.ts
index a7023981d..d0a91c98d 100644
--- a/apps/server/src/services/llm/tools/relationship_tool.ts
+++ b/apps/server/src/services/llm/tools/relationship_tool.ts
@@ -312,16 +312,7 @@ export class RelationshipTool implements ToolHandler {
             }
 
             // Get the AI service for relationship suggestion
-            const aiService = aiServiceManager.getService();
-
-            if (!aiService) {
-                log.error('No AI service available for relationship suggestions');
-                return {
-                    success: false,
-                    message: 'AI service not available for relationship suggestions',
-                    relatedNotes: relatedResult.relatedNotes
-                };
-            }
+            const aiService = await aiServiceManager.getService();
 
             log.info(`Using ${aiService.getName()} to suggest relationships for ${relatedResult.relatedNotes.length} related notes`);
 
diff --git a/apps/server/src/services/llm/tools/search_notes_tool.ts b/apps/server/src/services/llm/tools/search_notes_tool.ts
index 09b3fc645..152187dec 100644
--- a/apps/server/src/services/llm/tools/search_notes_tool.ts
+++ b/apps/server/src/services/llm/tools/search_notes_tool.ts
@@ -122,10 +122,10 @@ export class SearchNotesTool implements ToolHandler {
             // If summarization is requested
             if (summarize) {
                 // Try to get an LLM service for summarization
-                const llmService = aiServiceManager.getService();
-                if (llmService) {
-                    try {
-                        const messages = [
+                try {
+                    const llmService = await aiServiceManager.getService();
+                    
+                    const messages = [
                             {
                                 role: "system" as const,
                                 content: "Summarize the following note content concisely while preserving key information. Keep your summary to about 3-4 sentences."
@@ -147,13 +147,12 @@ export class SearchNotesTool implements ToolHandler {
                             } as Record))
                         });
 
-                        if (result && result.text) {
-                            return result.text;
-                        }
-                    } catch (error) {
-                        log.error(`Error summarizing content: ${error}`);
-                        // Fall through to smart truncation if summarization fails
+                    if (result && result.text) {
+                        return result.text;
                     }
+                } catch (error) {
+                    log.error(`Error summarizing content: ${error}`);
+                    // Fall through to smart truncation if summarization fails
                 }
             }
 
diff --git a/apps/server/src/services/options_init.ts b/apps/server/src/services/options_init.ts
index 212f47366..5311a67f0 100644
--- a/apps/server/src/services/options_init.ts
+++ b/apps/server/src/services/options_init.ts
@@ -195,26 +195,32 @@ const defaultOptions: DefaultOption[] = [
     // AI Options
     { name: "aiEnabled", value: "false", isSynced: true },
     { name: "openaiApiKey", value: "", isSynced: false },
-    { name: "openaiDefaultModel", value: "gpt-4o", isSynced: true },
-    { name: "openaiEmbeddingModel", value: "text-embedding-3-small", isSynced: true },
+    { name: "openaiDefaultModel", value: "", isSynced: true },
+    { name: "openaiEmbeddingModel", value: "", isSynced: true },
     { name: "openaiBaseUrl", value: "https://api.openai.com/v1", isSynced: true },
     { name: "anthropicApiKey", value: "", isSynced: false },
-    { name: "anthropicDefaultModel", value: "claude-3-opus-20240229", isSynced: true },
-    { name: "voyageEmbeddingModel", value: "voyage-2", isSynced: true },
+    { name: "anthropicDefaultModel", value: "", isSynced: true },
+    { name: "voyageEmbeddingModel", value: "", isSynced: true },
     { name: "voyageApiKey", value: "", isSynced: false },
     { name: "anthropicBaseUrl", value: "https://api.anthropic.com/v1", isSynced: true },
     { name: "ollamaEnabled", value: "false", isSynced: true },
-    { name: "ollamaDefaultModel", value: "llama3", isSynced: true },
+    { name: "ollamaDefaultModel", value: "", isSynced: true },
     { name: "ollamaBaseUrl", value: "http://localhost:11434", isSynced: true },
-    { name: "ollamaEmbeddingModel", value: "nomic-embed-text", isSynced: true },
+    { name: "ollamaEmbeddingModel", value: "", isSynced: true },
     { name: "embeddingAutoUpdateEnabled", value: "true", isSynced: true },
 
+    // Embedding-specific provider options
+    { name: "openaiEmbeddingApiKey", value: "", isSynced: false },
+    { name: "openaiEmbeddingBaseUrl", value: "https://api.openai.com/v1", isSynced: true },
+    { name: "voyageEmbeddingBaseUrl", value: "https://api.voyageai.com/v1", isSynced: true },
+    { name: "ollamaEmbeddingBaseUrl", value: "http://localhost:11434", isSynced: true },
+
     // Adding missing AI options
     { name: "aiTemperature", value: "0.7", isSynced: true },
     { name: "aiSystemPrompt", value: "", isSynced: true },
-    { name: "aiProviderPrecedence", value: "openai,anthropic,ollama", isSynced: true },
+    { name: "aiSelectedProvider", value: "openai", isSynced: true },
     { name: "embeddingDimensionStrategy", value: "auto", isSynced: true },
-    { name: "embeddingProviderPrecedence", value: "openai,voyage,ollama,local", isSynced: true },
+    { name: "embeddingSelectedProvider", value: "openai", isSynced: true },
     { name: "embeddingSimilarityThreshold", value: "0.75", isSynced: true },
     { name: "enableAutomaticIndexing", value: "true", isSynced: true },
     { name: "maxNotesPerLlmQuery", value: "3", isSynced: true },
diff --git a/package.json b/package.json
index 57d53a28e..c5d6308c4 100644
--- a/package.json
+++ b/package.json
@@ -27,16 +27,16 @@
   "private": true,
   "devDependencies": {
     "@electron/rebuild": "4.0.1",
-    "@nx/devkit": "21.1.2",
-    "@nx/esbuild": "21.1.2",
-    "@nx/eslint": "21.1.2",
-    "@nx/eslint-plugin": "21.1.2",
-    "@nx/express": "21.1.2",
-    "@nx/js": "21.1.2",
-    "@nx/node": "21.1.2",
-    "@nx/playwright": "21.1.2",
-    "@nx/vite": "21.1.2",
-    "@nx/web": "21.1.2",
+    "@nx/devkit": "21.1.3",
+    "@nx/esbuild": "21.1.3",
+    "@nx/eslint": "21.1.3",
+    "@nx/eslint-plugin": "21.1.3",
+    "@nx/express": "21.1.3",
+    "@nx/js": "21.1.3",
+    "@nx/node": "21.1.3",
+    "@nx/playwright": "21.1.3",
+    "@nx/vite": "21.1.3",
+    "@nx/web": "21.1.3",
     "@playwright/test": "^1.36.0",
     "@triliumnext/server": "workspace:*",
     "@types/express": "^4.17.21",
@@ -53,7 +53,7 @@
     "jiti": "2.4.2",
     "jsdom": "~26.1.0",
     "jsonc-eslint-parser": "^2.1.0",
-    "nx": "21.1.2",
+    "nx": "21.1.3",
     "react-refresh": "^0.17.0",
     "tslib": "^2.3.0",
     "tsx": "4.19.4",
diff --git a/packages/commons/src/lib/options_interface.ts b/packages/commons/src/lib/options_interface.ts
index 32f731936..77c3b2a68 100644
--- a/packages/commons/src/lib/options_interface.ts
+++ b/packages/commons/src/lib/options_interface.ts
@@ -132,26 +132,29 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions=16.0.0}
     deprecated: This functionality has been moved to @npmcli/fs
 
-  '@nx/devkit@21.1.2':
-    resolution: {integrity: sha512-1dgjwSsNDdp/VXydZnSfzfVwySEB3C9yjzeIw6+3+nRvZfH16a7ggZE7MF5sJTq4d+01hAgIDz3KyvGa6Jf73g==}
+  '@nx/devkit@21.1.3':
+    resolution: {integrity: sha512-NSNXdn+PaNoPcxAKIhnZUbOA91Jzgk68paZEiABzAhkvfmrE5jM6VDMT6sJZ8lHWocrf6QFnzAOon1R4MoBeZw==}
     peerDependencies:
-      nx: 21.1.2
+      nx: 21.1.3
 
-  '@nx/esbuild@21.1.2':
-    resolution: {integrity: sha512-6h3f8mC/5e2JxFAJaE4kLALkaoAs0nVB3aFBV+nd3+0mwywbcnMQ+dibvGCrBz2EPYlWczo43upAFEvvqpdUag==}
+  '@nx/esbuild@21.1.3':
+    resolution: {integrity: sha512-yYbD5wtc0nsSJq7v6F/tbfZwAxvvZfLxowdK4f30RgPdMnIgVW8Aqwyu3czDnLrmORJeuZ10NiGHp5pZtkGeYQ==}
     peerDependencies:
       esbuild: '>=0.25.0'
     peerDependenciesMeta:
       esbuild:
         optional: true
 
-  '@nx/eslint-plugin@21.1.2':
-    resolution: {integrity: sha512-kwhwe6e8dZ0pf5CYPq4OBck15NEJrfuivCEGRTIDZWu3WDYJIw7OvhfyCdGuoZLeHGoCVRjIU6xV5hOzkD9RSw==}
+  '@nx/eslint-plugin@21.1.3':
+    resolution: {integrity: sha512-xmh3bsK7yVQiEm0O5C3cD/J1P++iWQbEUl5rnysNxgHLh6gxkIh+4GLyRS8/05gbd6+JD1WKuzn77/wGq1gohw==}
     peerDependencies:
       '@typescript-eslint/parser': ^6.13.2 || ^7.0.0 || ^8.0.0
       eslint-config-prettier: ^10.0.0
@@ -3339,8 +3339,8 @@ packages:
       eslint-config-prettier:
         optional: true
 
-  '@nx/eslint@21.1.2':
-    resolution: {integrity: sha512-Mp8u0RlkhxYtZ47d2ou6t8XIpRy7N/n23OzikqMro4Wt/DK1irGyShSoNIqdGdwalAE5MG1OFXspttXB+y/wOQ==}
+  '@nx/eslint@21.1.3':
+    resolution: {integrity: sha512-g4Os1AfTjS+51a6+X+5ZgY/J7TGIKdc1byORreaSnLXtN9BU6r4WKzGkT5TAAXS+UXXmSih7QAJhKPur2IHddQ==}
     peerDependencies:
       '@zkochan/js-yaml': 0.0.7
       eslint: ^8.0.0 || ^9.0.0
@@ -3348,97 +3348,97 @@ packages:
       '@zkochan/js-yaml':
         optional: true
 
-  '@nx/express@21.1.2':
-    resolution: {integrity: sha512-YYulIUJY9Hm2U4qWXJXgWFvIY2Hj39jdVs8p+Tsy/LuEV1NfDu1xAZxPdedQlevEvl3+KLCrt2SJ7JVohjvk7g==}
+  '@nx/express@21.1.3':
+    resolution: {integrity: sha512-CbfxgkDJmx6iz8eegcNDa+ygPbfyQ7lIVwEDLGECFEaL5W48IwDlydbBYjbtPD2VfXFHX1z8zbgeuC1zMnWuKA==}
     peerDependencies:
       express: ^4.21.2
     peerDependenciesMeta:
       express:
         optional: true
 
-  '@nx/jest@21.1.2':
-    resolution: {integrity: sha512-y4VZita9LFb6XajulRIwjMcqHU6/f73C4SNSH6IM5BYmkN68ovICmzTGvoaL7wGTaYrA4Moh/WoKwEwQWKxRPQ==}
+  '@nx/jest@21.1.3':
+    resolution: {integrity: sha512-Wn3dqxvJ+O3OYiJ/h0Mmr4huc3JS+nZquUMAm19aJS8y6QVWRzGQGPxEJQ5jzoe407VMIKjiQ4LPhoV/xrNwbA==}
 
-  '@nx/js@21.1.2':
-    resolution: {integrity: sha512-ZF6Zf4Ys+RBvH0GoQHio94C/0N07Px/trAvseMuQ8PKc0tSkXycu/EBc1uAZQvgJThR5o3diAKtIQug77pPYMQ==}
+  '@nx/js@21.1.3':
+    resolution: {integrity: sha512-pwn1tgWX8sxh+VKZRZl9VkabXkEyeELFCgkWS/on2Y1J6W2dMBcmyGuZAeLef2GkUNaR79VMWIqvPaK0JLyf4g==}
     peerDependencies:
       verdaccio: ^6.0.5
     peerDependenciesMeta:
       verdaccio:
         optional: true
 
-  '@nx/node@21.1.2':
-    resolution: {integrity: sha512-BCKooOKT04MJDzLy6U4w3mFWhHCsuoMXqUjcd5g/3zf4bFXOK3ooklvVkxjHUQxRXVG/uPJ+ZcgTC1SE0vpS6g==}
+  '@nx/node@21.1.3':
+    resolution: {integrity: sha512-tFsdkQ7RJZjAmivRkmVRAbY3ck7u+RLhcswelx2kXRsRozrWxX4Da+pECUePt2wq/HnrBGujPgGrZz7pMpZrbQ==}
 
-  '@nx/nx-darwin-arm64@21.1.2':
-    resolution: {integrity: sha512-9dO32jd+h7SrvQafJph6b7Bsmp2IotTE0w7dAGb4MGBQni3JWCXaxlMMpWUZXWW1pM5uIkFJO5AASW4UOI7w2w==}
+  '@nx/nx-darwin-arm64@21.1.3':
+    resolution: {integrity: sha512-gbBKQrw9ecjXHVs7Kwaht5Dip//NBCgmnkf3GGoA40ad3zyvHDe+MBWMxueRToUVW/mDPh8b5lvLbmFApiY6sQ==}
     cpu: [arm64]
     os: [darwin]
 
-  '@nx/nx-darwin-x64@21.1.2':
-    resolution: {integrity: sha512-5sf+4PRVg9pDVgD53NE1hoPz4lC8Ni34UovQsOrZgDvwU5mqPbIhTzVYRDH86i/086AcCvjT5tEt7rEcuRwlKw==}
+  '@nx/nx-darwin-x64@21.1.3':
+    resolution: {integrity: sha512-yGDWqxwNty1BJcuvZlwGGravAhg8eIRMEIp2omfIxeyfZEVA4b7egwMCqczwU2Li/StNjTtzrUe1HPWgcCVAuQ==}
     cpu: [x64]
     os: [darwin]
 
-  '@nx/nx-freebsd-x64@21.1.2':
-    resolution: {integrity: sha512-E5HR44fimXlQuAgn/tP9esmvxbzt/92AIl0PBT6L3Juh/xYiXKWhda63H4+UNT8AcLRxVXwfZrGPuGCDs+7y/Q==}
+  '@nx/nx-freebsd-x64@21.1.3':
+    resolution: {integrity: sha512-vpZPfSQgNIQ0vmnQA26DlJKZog20ISdS14ir234mvCaJJFdlgWGcpyEOSCU3Vg+32Z/VsSx7kIkBwRhfEZ73Ag==}
     cpu: [x64]
     os: [freebsd]
 
-  '@nx/nx-linux-arm-gnueabihf@21.1.2':
-    resolution: {integrity: sha512-V4n6DE+r12gwJHFjZs+e2GmWYZdhpgA2DYWbsYWRYb1XQCNUg4vPzt+YFzWZ+K2o91k93EBnlLfrag7CqxUslw==}
+  '@nx/nx-linux-arm-gnueabihf@21.1.3':
+    resolution: {integrity: sha512-R2GzEyHvyree2m7w+e/MOZjUY/l99HbW4E/jJl5BBXRGEAnGTIx9fOxSDiOW5QK6U0oZb2YO2b565t+IC+7rBQ==}
     cpu: [arm]
     os: [linux]
 
-  '@nx/nx-linux-arm64-gnu@21.1.2':
-    resolution: {integrity: sha512-NFhsp27O+mS3r7PWLmJgyZy42WQ72c2pTQSpYfhaBbZPTI5DqBHdANa0sEPmV+ON24qkl5CZKvsmhzjsNmyW6A==}
+  '@nx/nx-linux-arm64-gnu@21.1.3':
+    resolution: {integrity: sha512-TlFT0G5gO6ujdkT7KUmvS2bwurvpV3olQwchqW1rQwuZ1eEQ1GVDuyzg49UG7lgESYruFn2HRhBf4V+iaD8WIw==}
     cpu: [arm64]
     os: [linux]
 
-  '@nx/nx-linux-arm64-musl@21.1.2':
-    resolution: {integrity: sha512-BgS9npARwcnw+hoaRsbas6vdBAJRBAj5qSeL57LO8Dva+e/6PYqoNyVJ0BgJ98xPXDpzM/NnpeRsndQGpLyhDw==}
+  '@nx/nx-linux-arm64-musl@21.1.3':
+    resolution: {integrity: sha512-YkdzrZ7p2Y0YpteRyT9lPKhfuz2t5rNFQ87x9WHK2/cFD6H6M42Fg2JldCPIVj2chN9liH+s5ougW5oPQpZyKw==}
     cpu: [arm64]
     os: [linux]
 
-  '@nx/nx-linux-x64-gnu@21.1.2':
-    resolution: {integrity: sha512-tjBINbymQgxnIlNK/m6B0P5eiGRSHSYPNkFdh3+sra80AP/ymHGLRxxZy702Ga2xg8RVr9zEvuXYHI+QBa1YmA==}
+  '@nx/nx-linux-x64-gnu@21.1.3':
+    resolution: {integrity: sha512-nnHxhakNCr4jR1y13g0yS/UOmn5aXkJ+ZA1R6jFQxIwLv3Ocy05i0ZvU7rPOtflluDberxEop8xzoiuEZXDa/w==}
     cpu: [x64]
     os: [linux]
 
-  '@nx/nx-linux-x64-musl@21.1.2':
-    resolution: {integrity: sha512-+0V0YAOWMh1wvpQZuayQ7y+sj2MhE3l7z0JMD9SX/4xv9zLOWGv+EiUmN/fGoU/mwsSkH2wTCo6G6quKF1E8jQ==}
+  '@nx/nx-linux-x64-musl@21.1.3':
+    resolution: {integrity: sha512-poPt/LnFbq54CA3PZ1af8wcdQ4VsWRuA9w1Q1/G1BhCfDUAVIOZ0mhH1NzFpPwCxgVZ1TbNCZWhV2qjVRwQtlw==}
     cpu: [x64]
     os: [linux]
 
-  '@nx/nx-win32-arm64-msvc@21.1.2':
-    resolution: {integrity: sha512-E+ECMQIMJ6R47BMW5YpDyOhTqczvFaL8k24umRkcvlRh3SraczyxBVPkYHDukDp7tCeIszc5EvdWc83C3W8U4w==}
+  '@nx/nx-win32-arm64-msvc@21.1.3':
+    resolution: {integrity: sha512-gBSVMRkXRqxTKgj/dabAD1EaptROy64fEtlU1llPz/RtcJcVhIlDczBF/y2WSD6A72cSv6zF/F1n3NrekNSfBA==}
     cpu: [arm64]
     os: [win32]
 
-  '@nx/nx-win32-x64-msvc@21.1.2':
-    resolution: {integrity: sha512-J9rNTBOS7Ld6CybU/cou1Fg52AHSYsiwpZISM2RNM0XIoVSDk3Jsvh4OJgS2rvV0Sp/cgDg3ieOMAreekH+TKw==}
+  '@nx/nx-win32-x64-msvc@21.1.3':
+    resolution: {integrity: sha512-k3/1b2dLQjnWzrg2UqHDLCoaqEBx2SRgujjYCACRJ12vmYH2gTyFX2UPXikVbbpaTJNeXv8eaCzyCKhuvPK1sQ==}
     cpu: [x64]
     os: [win32]
 
-  '@nx/playwright@21.1.2':
-    resolution: {integrity: sha512-XSfxoB+LeGFVpzzw59pjMjurOXmLEngGMqk+Z/4QT1A2lzBG4HccVrZQ8UiSxAGCbK+O7MFjy1r0k0z80EjYgg==}
+  '@nx/playwright@21.1.3':
+    resolution: {integrity: sha512-6Cq8lgQQsSutx5hZG2RChFQFJ9cVgJf9ymqvBohLCDPcC6/d2QflMdoqT4yjaOd5TqStk3ZC+elll6tnTY+QYA==}
     peerDependencies:
       '@playwright/test': ^1.36.0
     peerDependenciesMeta:
       '@playwright/test':
         optional: true
 
-  '@nx/vite@21.1.2':
-    resolution: {integrity: sha512-qKb3CTPtcs3MsDebNW7PUS10IDB1+w//iXKFobwmclH4uW/HFUMRcdUrIsdcQfdmQPjGNTTM2fwmbgWJC4qmAw==}
+  '@nx/vite@21.1.3':
+    resolution: {integrity: sha512-xd3WFYQDIZFm3DPza1fY52dVa1km1gCJyoE9/2s+m9Jbvxu40BukdSw37SZVgCtVqyNjsl4rrlXOmzOIKLb98g==}
     peerDependencies:
       vite: ^5.0.0 || ^6.0.0
       vitest: ^1.3.1 || ^2.0.0 || ^3.0.0
 
-  '@nx/web@21.1.2':
-    resolution: {integrity: sha512-ONw3bEO6rc9DqM9Jnt6Rc5xkSBMzruWA2KvHVlU4qaoUs1VKbnmJ28dM72lFMn8wbOOeq+RG7GC2nBpifBPLHw==}
+  '@nx/web@21.1.3':
+    resolution: {integrity: sha512-9UV3uacxJ6oMYPfXbPDq1jadM6nPMs13QhSEpjQLAxNDi4ay0zTOobbHZG6LYnf69dAFEIppoayiS42Kuk6L3Q==}
 
-  '@nx/workspace@21.1.2':
-    resolution: {integrity: sha512-I4e/X/GN0Vx3FDZv/7bFYmXfOPmcMI3cDO/rg+TqudsuxVM7tJ7+8jtwdpU4I2IEpI6oU9FZ7Fu9R2uNqL5rrQ==}
+  '@nx/workspace@21.1.3':
+    resolution: {integrity: sha512-SAObZmW1cx0hRddC2PCFWJBHpzdjsTGNArJta8iyzfrbP9KAxQd8jjDBZvXLpXU6YMOw0fLwm8YAD2E1xvIoyw==}
 
   '@open-draft/deferred-promise@2.2.0':
     resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==}
@@ -4777,10 +4777,6 @@ packages:
     peerDependencies:
       typescript: '>=4.8.4 <5.9.0'
 
-  '@typescript-eslint/scope-manager@8.32.1':
-    resolution: {integrity: sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
   '@typescript-eslint/scope-manager@8.33.1':
     resolution: {integrity: sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4791,13 +4787,6 @@ packages:
     peerDependencies:
       typescript: '>=4.8.4 <5.9.0'
 
-  '@typescript-eslint/type-utils@8.32.1':
-    resolution: {integrity: sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '>=4.8.4 <5.9.0'
-
   '@typescript-eslint/type-utils@8.33.1':
     resolution: {integrity: sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4805,33 +4794,16 @@ packages:
       eslint: ^8.57.0 || ^9.0.0
       typescript: '>=4.8.4 <5.9.0'
 
-  '@typescript-eslint/types@8.32.1':
-    resolution: {integrity: sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
   '@typescript-eslint/types@8.33.1':
     resolution: {integrity: sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  '@typescript-eslint/typescript-estree@8.32.1':
-    resolution: {integrity: sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      typescript: '>=4.8.4 <5.9.0'
-
   '@typescript-eslint/typescript-estree@8.33.1':
     resolution: {integrity: sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     peerDependencies:
       typescript: '>=4.8.4 <5.9.0'
 
-  '@typescript-eslint/utils@8.32.1':
-    resolution: {integrity: sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-    peerDependencies:
-      eslint: ^8.57.0 || ^9.0.0
-      typescript: '>=4.8.4 <5.9.0'
-
   '@typescript-eslint/utils@8.33.1':
     resolution: {integrity: sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4839,10 +4811,6 @@ packages:
       eslint: ^8.57.0 || ^9.0.0
       typescript: '>=4.8.4 <5.9.0'
 
-  '@typescript-eslint/visitor-keys@8.32.1':
-    resolution: {integrity: sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==}
-    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
   '@typescript-eslint/visitor-keys@8.33.1':
     resolution: {integrity: sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -9495,8 +9463,8 @@ packages:
   nwsapi@2.2.20:
     resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==}
 
-  nx@21.1.2:
-    resolution: {integrity: sha512-oczAEOOkQHElxCXs2g2jXDRabDRsmub/h5SAgqAUDSJ2CRnYGVVlgZX7l+o+A9kSqfONyLy5FlJ1pSWlvPuG4w==}
+  nx@21.1.3:
+    resolution: {integrity: sha512-GZ7+Bve4xOVIk/hb9nN16fVqVq5PNNyFom1SCQbEGhGkyABJF8kA4JImCKhZpZyg1CtZeUrkPHK4xNO+rw9G5w==}
     hasBin: true
     peerDependencies:
       '@swc-node/register': ^1.8.0
@@ -12900,11 +12868,6 @@ packages:
     resolution: {integrity: sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==}
     engines: {node: '>= 6'}
 
-  yaml@2.7.1:
-    resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==}
-    engines: {node: '>= 14'}
-    hasBin: true
-
   yaml@2.8.0:
     resolution: {integrity: sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==}
     engines: {node: '>= 14.6'}
@@ -13058,10 +13021,10 @@ snapshots:
       '@babel/helper-compilation-targets': 7.27.0
       '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10)
       '@babel/helpers': 7.27.0
-      '@babel/parser': 7.27.2
+      '@babel/parser': 7.27.5
       '@babel/template': 7.27.0
       '@babel/traverse': 7.27.0
-      '@babel/types': 7.27.1
+      '@babel/types': 7.27.6
       convert-source-map: 2.0.0
       debug: 4.4.1(supports-color@6.0.0)
       gensync: 1.0.0-beta.2
@@ -13072,8 +13035,8 @@ snapshots:
 
   '@babel/generator@7.27.0':
     dependencies:
-      '@babel/parser': 7.27.2
-      '@babel/types': 7.27.1
+      '@babel/parser': 7.27.5
+      '@babel/types': 7.27.6
       '@jridgewell/gen-mapping': 0.3.8
       '@jridgewell/trace-mapping': 0.3.25
       jsesc: 3.1.0
@@ -13192,7 +13155,7 @@ snapshots:
   '@babel/helpers@7.27.0':
     dependencies:
       '@babel/template': 7.27.0
-      '@babel/types': 7.27.1
+      '@babel/types': 7.27.6
 
   '@babel/parser@7.27.0':
     dependencies:
@@ -13200,7 +13163,7 @@ snapshots:
 
   '@babel/parser@7.27.2':
     dependencies:
-      '@babel/types': 7.27.1
+      '@babel/types': 7.27.6
 
   '@babel/parser@7.27.5':
     dependencies:
@@ -13795,8 +13758,8 @@ snapshots:
   '@babel/template@7.27.0':
     dependencies:
       '@babel/code-frame': 7.26.2
-      '@babel/parser': 7.27.2
-      '@babel/types': 7.27.1
+      '@babel/parser': 7.27.5
+      '@babel/types': 7.27.6
 
   '@babel/traverse@7.27.0':
     dependencies:
@@ -16204,24 +16167,24 @@ snapshots:
       mkdirp: 1.0.4
       rimraf: 3.0.2
 
-  '@nx/devkit@21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
+  '@nx/devkit@21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
     dependencies:
       ejs: 3.1.10
       enquirer: 2.3.6
       ignore: 5.3.2
       minimatch: 9.0.3
-      nx: 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
+      nx: 21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
       semver: 7.7.2
       tmp: 0.2.3
       tslib: 2.8.1
       yargs-parser: 21.1.1
 
-  '@nx/esbuild@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.5)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
+  '@nx/esbuild@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.25.5)(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       picocolors: 1.1.1
-      tinyglobby: 0.2.13
+      tinyglobby: 0.2.14
       tsconfig-paths: 4.2.0
       tslib: 2.8.1
     optionalDependencies:
@@ -16235,13 +16198,13 @@ snapshots:
       - supports-color
       - verdaccio
 
-  '@nx/eslint-plugin@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@2.4.2)))(eslint@9.28.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)':
+  '@nx/eslint-plugin@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@typescript-eslint/parser@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(eslint-config-prettier@10.1.5(eslint@9.28.0(jiti@2.4.2)))(eslint@9.28.0(jiti@2.4.2))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       '@typescript-eslint/parser': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
-      '@typescript-eslint/type-utils': 8.32.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
-      '@typescript-eslint/utils': 8.32.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
+      '@typescript-eslint/type-utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
+      '@typescript-eslint/utils': 8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
       chalk: 4.1.2
       confusing-browser-globals: 1.0.11
       globals: 15.15.0
@@ -16261,10 +16224,10 @@ snapshots:
       - typescript
       - verdaccio
 
-  '@nx/eslint@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
+  '@nx/eslint@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       eslint: 9.28.0(jiti@2.4.2)
       semver: 7.7.2
       tslib: 2.8.1
@@ -16280,11 +16243,11 @@ snapshots:
       - supports-color
       - verdaccio
 
-  '@nx/express@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.28.0(jiti@2.4.2))(express@4.21.2)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)':
+  '@nx/express@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.28.0(jiti@2.4.2))(express@4.21.2)(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/node': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/node': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)
       tslib: 2.8.1
     optionalDependencies:
       express: 4.21.2
@@ -16304,12 +16267,12 @@ snapshots:
       - typescript
       - verdaccio
 
-  '@nx/jest@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(babel-plugin-macros@3.1.0)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)':
+  '@nx/jest@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(babel-plugin-macros@3.1.0)(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)':
     dependencies:
       '@jest/reporters': 29.7.0
       '@jest/test-result': 29.7.0
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3)
       identity-obj-proxy: 3.0.0
       jest-config: 29.7.0(@types/node@22.15.30)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))
@@ -16335,7 +16298,7 @@ snapshots:
       - typescript
       - verdaccio
 
-  '@nx/js@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
+  '@nx/js@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
     dependencies:
       '@babel/core': 7.26.10
       '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.10)
@@ -16344,8 +16307,8 @@ snapshots:
       '@babel/preset-env': 7.26.9(@babel/core@7.26.10)
       '@babel/preset-typescript': 7.27.0(@babel/core@7.26.10)
       '@babel/runtime': 7.27.1
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/workspace': 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/workspace': 21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
       '@zkochan/js-yaml': 0.0.7
       babel-plugin-const-enum: 1.2.0(@babel/core@7.26.10)
       babel-plugin-macros: 3.1.0
@@ -16364,7 +16327,7 @@ snapshots:
       picomatch: 4.0.2
       semver: 7.7.2
       source-map-support: 0.5.19
-      tinyglobby: 0.2.13
+      tinyglobby: 0.2.14
       tslib: 2.8.1
     transitivePeerDependencies:
       - '@babel/traverse'
@@ -16374,12 +16337,12 @@ snapshots:
       - nx
       - supports-color
 
-  '@nx/node@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)':
+  '@nx/node@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/eslint': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/jest': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(babel-plugin-macros@3.1.0)(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/eslint': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/jest': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(babel-plugin-macros@3.1.0)(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(ts-node@10.9.2(@swc/core@1.11.29(@swc/helpers@0.5.17))(@types/node@22.15.30)(typescript@5.8.3))(typescript@5.8.3)
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       kill-port: 1.6.1
       tcp-port-used: 1.0.2
       tslib: 2.8.1
@@ -16399,41 +16362,41 @@ snapshots:
       - typescript
       - verdaccio
 
-  '@nx/nx-darwin-arm64@21.1.2':
+  '@nx/nx-darwin-arm64@21.1.3':
     optional: true
 
-  '@nx/nx-darwin-x64@21.1.2':
+  '@nx/nx-darwin-x64@21.1.3':
     optional: true
 
-  '@nx/nx-freebsd-x64@21.1.2':
+  '@nx/nx-freebsd-x64@21.1.3':
     optional: true
 
-  '@nx/nx-linux-arm-gnueabihf@21.1.2':
+  '@nx/nx-linux-arm-gnueabihf@21.1.3':
     optional: true
 
-  '@nx/nx-linux-arm64-gnu@21.1.2':
+  '@nx/nx-linux-arm64-gnu@21.1.3':
     optional: true
 
-  '@nx/nx-linux-arm64-musl@21.1.2':
+  '@nx/nx-linux-arm64-musl@21.1.3':
     optional: true
 
-  '@nx/nx-linux-x64-gnu@21.1.2':
+  '@nx/nx-linux-x64-gnu@21.1.3':
     optional: true
 
-  '@nx/nx-linux-x64-musl@21.1.2':
+  '@nx/nx-linux-x64-musl@21.1.3':
     optional: true
 
-  '@nx/nx-win32-arm64-msvc@21.1.2':
+  '@nx/nx-win32-arm64-msvc@21.1.3':
     optional: true
 
-  '@nx/nx-win32-x64-msvc@21.1.2':
+  '@nx/nx-win32-x64-msvc@21.1.3':
     optional: true
 
-  '@nx/playwright@21.1.2(@babel/traverse@7.27.0)(@playwright/test@1.52.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)':
+  '@nx/playwright@21.1.3(@babel/traverse@7.27.0)(@playwright/test@1.52.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/eslint': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/eslint': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(@zkochan/js-yaml@0.0.7)(eslint@9.28.0(jiti@2.4.2))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3)
       minimatch: 9.0.3
       tslib: 2.8.1
@@ -16451,10 +16414,10 @@ snapshots:
       - typescript
       - verdaccio
 
-  '@nx/vite@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.87.0)(sass@1.87.0)(stylus@0.64.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.0)(tsx@4.19.4)(yaml@2.8.0))(vitest@3.2.2)':
+  '@nx/vite@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.30)(jiti@2.4.2)(less@4.1.3)(sass-embedded@1.87.0)(sass@1.87.0)(stylus@0.64.0)(sugarss@4.0.1(postcss@8.5.3))(terser@5.39.0)(tsx@4.19.4)(yaml@2.8.0))(vitest@3.2.2)':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       '@phenomnomnominal/tsquery': 5.0.1(typescript@5.8.3)
       '@swc/helpers': 0.5.17
       ajv: 8.17.1
@@ -16474,10 +16437,10 @@ snapshots:
       - typescript
       - verdaccio
 
-  '@nx/web@21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
+  '@nx/web@21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
-      '@nx/js': 21.1.2(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/js': 21.1.3(@babel/traverse@7.27.0)(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       detect-port: 1.6.1
       http-server: 14.1.1
       picocolors: 1.1.1
@@ -16491,13 +16454,13 @@ snapshots:
       - supports-color
       - verdaccio
 
-  '@nx/workspace@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))':
+  '@nx/workspace@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))':
     dependencies:
-      '@nx/devkit': 21.1.2(nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
+      '@nx/devkit': 21.1.3(nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)))
       '@zkochan/js-yaml': 0.0.7
       chalk: 4.1.2
       enquirer: 2.3.6
-      nx: 21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
+      nx: 21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17))
       picomatch: 4.0.2
       tslib: 2.8.1
       yargs-parser: 21.1.1
@@ -17861,11 +17824,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/scope-manager@8.32.1':
-    dependencies:
-      '@typescript-eslint/types': 8.32.1
-      '@typescript-eslint/visitor-keys': 8.32.1
-
   '@typescript-eslint/scope-manager@8.33.1':
     dependencies:
       '@typescript-eslint/types': 8.33.1
@@ -17875,17 +17833,6 @@ snapshots:
     dependencies:
       typescript: 5.8.3
 
-  '@typescript-eslint/type-utils@8.32.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
-    dependencies:
-      '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
-      '@typescript-eslint/utils': 8.32.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)
-      debug: 4.4.1(supports-color@6.0.0)
-      eslint: 9.28.0(jiti@2.4.2)
-      ts-api-utils: 2.1.0(typescript@5.8.3)
-      typescript: 5.8.3
-    transitivePeerDependencies:
-      - supports-color
-
   '@typescript-eslint/type-utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
     dependencies:
       '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.8.3)
@@ -17897,24 +17844,8 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/types@8.32.1': {}
-
   '@typescript-eslint/types@8.33.1': {}
 
-  '@typescript-eslint/typescript-estree@8.32.1(typescript@5.8.3)':
-    dependencies:
-      '@typescript-eslint/types': 8.32.1
-      '@typescript-eslint/visitor-keys': 8.32.1
-      debug: 4.4.1(supports-color@6.0.0)
-      fast-glob: 3.3.3
-      is-glob: 4.0.3
-      minimatch: 9.0.5
-      semver: 7.7.2
-      ts-api-utils: 2.1.0(typescript@5.8.3)
-      typescript: 5.8.3
-    transitivePeerDependencies:
-      - supports-color
-
   '@typescript-eslint/typescript-estree@8.33.1(typescript@5.8.3)':
     dependencies:
       '@typescript-eslint/project-service': 8.33.1(typescript@5.8.3)
@@ -17931,17 +17862,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/utils@8.32.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
-    dependencies:
-      '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2))
-      '@typescript-eslint/scope-manager': 8.32.1
-      '@typescript-eslint/types': 8.32.1
-      '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.8.3)
-      eslint: 9.28.0(jiti@2.4.2)
-      typescript: 5.8.3
-    transitivePeerDependencies:
-      - supports-color
-
   '@typescript-eslint/utils@8.33.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)':
     dependencies:
       '@eslint-community/eslint-utils': 4.7.0(eslint@9.28.0(jiti@2.4.2))
@@ -17953,11 +17873,6 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/visitor-keys@8.32.1':
-    dependencies:
-      '@typescript-eslint/types': 8.32.1
-      eslint-visitor-keys: 4.2.0
-
   '@typescript-eslint/visitor-keys@8.33.1':
     dependencies:
       '@typescript-eslint/types': 8.33.1
@@ -21429,7 +21344,7 @@ snapshots:
       fs.realpath: 1.0.0
       inflight: 1.0.6
       inherits: 2.0.4
-      minimatch: 3.0.4
+      minimatch: 3.1.2
       once: 1.4.0
       path-is-absolute: 1.0.1
 
@@ -23674,7 +23589,7 @@ snapshots:
       proc-log: 5.0.0
       semver: 7.7.2
       tar: 7.4.3
-      tinyglobby: 0.2.13
+      tinyglobby: 0.2.14
       which: 5.0.0
     transitivePeerDependencies:
       - supports-color
@@ -23761,7 +23676,7 @@ snapshots:
 
   nwsapi@2.2.20: {}
 
-  nx@21.1.2(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)):
+  nx@21.1.3(@swc-node/register@1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3))(@swc/core@1.11.29(@swc/helpers@0.5.17)):
     dependencies:
       '@napi-rs/wasm-runtime': 0.2.4
       '@yarnpkg/lockfile': 1.1.0
@@ -23795,20 +23710,20 @@ snapshots:
       tree-kill: 1.2.2
       tsconfig-paths: 4.2.0
       tslib: 2.8.1
-      yaml: 2.7.1
+      yaml: 2.8.0
       yargs: 17.7.2
       yargs-parser: 21.1.1
     optionalDependencies:
-      '@nx/nx-darwin-arm64': 21.1.2
-      '@nx/nx-darwin-x64': 21.1.2
-      '@nx/nx-freebsd-x64': 21.1.2
-      '@nx/nx-linux-arm-gnueabihf': 21.1.2
-      '@nx/nx-linux-arm64-gnu': 21.1.2
-      '@nx/nx-linux-arm64-musl': 21.1.2
-      '@nx/nx-linux-x64-gnu': 21.1.2
-      '@nx/nx-linux-x64-musl': 21.1.2
-      '@nx/nx-win32-arm64-msvc': 21.1.2
-      '@nx/nx-win32-x64-msvc': 21.1.2
+      '@nx/nx-darwin-arm64': 21.1.3
+      '@nx/nx-darwin-x64': 21.1.3
+      '@nx/nx-freebsd-x64': 21.1.3
+      '@nx/nx-linux-arm-gnueabihf': 21.1.3
+      '@nx/nx-linux-arm64-gnu': 21.1.3
+      '@nx/nx-linux-arm64-musl': 21.1.3
+      '@nx/nx-linux-x64-gnu': 21.1.3
+      '@nx/nx-linux-x64-musl': 21.1.3
+      '@nx/nx-win32-arm64-msvc': 21.1.3
+      '@nx/nx-win32-x64-msvc': 21.1.3
       '@swc-node/register': 1.10.10(@swc/core@1.11.29(@swc/helpers@0.5.17))(@swc/types@0.1.21)(typescript@5.8.3)
       '@swc/core': 1.11.29(@swc/helpers@0.5.17)
     transitivePeerDependencies:
@@ -27601,8 +27516,6 @@ snapshots:
 
   yaml@2.0.0-1: {}
 
-  yaml@2.7.1: {}
-
   yaml@2.8.0: {}
 
   yargs-parser@13.1.2: