@@ -4,13 +4,15 @@ import { OpenAiEmbedder } from "../embedders/openai"
44import { CodeIndexOllamaEmbedder } from "../embedders/ollama"
55import { OpenAICompatibleEmbedder } from "../embedders/openai-compatible"
66import { GeminiEmbedder } from "../embedders/gemini"
7+ import { CodeIndexLmStudioEmbedder } from "../embedders/lmstudio"
78import { QdrantVectorStore } from "../vector-store/qdrant-client"
89
910// Mock the embedders and vector store
1011vitest . mock ( "../embedders/openai" )
1112vitest . mock ( "../embedders/ollama" )
1213vitest . mock ( "../embedders/openai-compatible" )
1314vitest . mock ( "../embedders/gemini" )
15+ vitest . mock ( "../embedders/lmstudio" )
1416vitest . mock ( "../vector-store/qdrant-client" )
1517
1618// Mock the embedding models module
@@ -23,6 +25,7 @@ const MockedOpenAiEmbedder = OpenAiEmbedder as MockedClass<typeof OpenAiEmbedder
2325const MockedCodeIndexOllamaEmbedder = CodeIndexOllamaEmbedder as MockedClass < typeof CodeIndexOllamaEmbedder >
2426const MockedOpenAICompatibleEmbedder = OpenAICompatibleEmbedder as MockedClass < typeof OpenAICompatibleEmbedder >
2527const MockedGeminiEmbedder = GeminiEmbedder as MockedClass < typeof GeminiEmbedder >
28+ const MockedCodeIndexLmStudioEmbedder = CodeIndexLmStudioEmbedder as MockedClass < typeof CodeIndexLmStudioEmbedder >
2629const MockedQdrantVectorStore = QdrantVectorStore as MockedClass < typeof QdrantVectorStore >
2730
2831// Import the mocked functions
@@ -305,6 +308,77 @@ describe("CodeIndexServiceFactory", () => {
305308 expect ( ( ) => factory . createEmbedder ( ) ) . toThrow ( "Gemini configuration missing for embedder creation" )
306309 } )
307310
311+ it ( "should pass model ID to LM Studio embedder when using LM Studio provider" , ( ) => {
312+ // Arrange
313+ const testModelId = "nomic-embed-text-v1.5"
314+ const testConfig = {
315+ embedderProvider : "lmstudio" ,
316+ modelId : testModelId ,
317+ lmStudioOptions : {
318+ lmStudioBaseUrl : "http://localhost:1234" ,
319+ } ,
320+ }
321+ mockConfigManager . getConfig . mockReturnValue ( testConfig as any )
322+
323+ // Act
324+ factory . createEmbedder ( )
325+
326+ // Assert
327+ expect ( MockedCodeIndexLmStudioEmbedder ) . toHaveBeenCalledWith ( {
328+ lmStudioBaseUrl : "http://localhost:1234" ,
329+ lmStudioModelId : testModelId ,
330+ } )
331+ } )
332+
333+ it ( "should handle undefined model ID for LM Studio embedder" , ( ) => {
334+ // Arrange
335+ const testConfig = {
336+ embedderProvider : "lmstudio" ,
337+ modelId : undefined ,
338+ lmStudioOptions : {
339+ lmStudioBaseUrl : "http://localhost:1234" ,
340+ } ,
341+ }
342+ mockConfigManager . getConfig . mockReturnValue ( testConfig as any )
343+
344+ // Act
345+ factory . createEmbedder ( )
346+
347+ // Assert
348+ expect ( MockedCodeIndexLmStudioEmbedder ) . toHaveBeenCalledWith ( {
349+ lmStudioBaseUrl : "http://localhost:1234" ,
350+ lmStudioModelId : undefined ,
351+ } )
352+ } )
353+
354+ it ( "should throw error when LM Studio base URL is missing" , ( ) => {
355+ // Arrange
356+ const testConfig = {
357+ embedderProvider : "lmstudio" ,
358+ modelId : "nomic-embed-text-v1.5" ,
359+ lmStudioOptions : {
360+ lmStudioBaseUrl : undefined ,
361+ } ,
362+ }
363+ mockConfigManager . getConfig . mockReturnValue ( testConfig as any )
364+
365+ // Act & Assert
366+ expect ( ( ) => factory . createEmbedder ( ) ) . toThrow ( "LM Studio configuration missing for embedder creation" )
367+ } )
368+
369+ it ( "should throw error when LM Studio options are missing" , ( ) => {
370+ // Arrange
371+ const testConfig = {
372+ embedderProvider : "lmstudio" ,
373+ modelId : "nomic-embed-text-v1.5" ,
374+ lmStudioOptions : undefined ,
375+ }
376+ mockConfigManager . getConfig . mockReturnValue ( testConfig as any )
377+
378+ // Act & Assert
379+ expect ( ( ) => factory . createEmbedder ( ) ) . toThrow ( "LM Studio configuration missing for embedder creation" )
380+ } )
381+
308382 it ( "should throw error for invalid embedder provider" , ( ) => {
309383 // Arrange
310384 const testConfig = {
@@ -524,6 +598,31 @@ describe("CodeIndexServiceFactory", () => {
524598 )
525599 } )
526600
601+ it ( "should use config.modelId for LM Studio provider" , ( ) => {
602+ // Arrange
603+ const testModelId = "nomic-embed-text-v1.5"
604+ const testConfig = {
605+ embedderProvider : "lmstudio" ,
606+ modelId : testModelId ,
607+ qdrantUrl : "http://localhost:6333" ,
608+ qdrantApiKey : "test-key" ,
609+ }
610+ mockConfigManager . getConfig . mockReturnValue ( testConfig as any )
611+ mockGetModelDimension . mockReturnValue ( 768 )
612+
613+ // Act
614+ factory . createVectorStore ( )
615+
616+ // Assert
617+ expect ( mockGetModelDimension ) . toHaveBeenCalledWith ( "lmstudio" , testModelId )
618+ expect ( MockedQdrantVectorStore ) . toHaveBeenCalledWith (
619+ "/test/workspace" ,
620+ "http://localhost:6333" ,
621+ 768 ,
622+ "test-key" ,
623+ )
624+ } )
625+
527626 it ( "should use default model when config.modelId is undefined" , ( ) => {
528627 // Arrange
529628 const testConfig = {
0 commit comments