From b1406342a86ab2f50e1df0162e7f9d56f17529bd Mon Sep 17 00:00:00 2001 From: Nahim EL ATMANI Date: Thu, 24 Jul 2025 21:41:35 -0700 Subject: [PATCH] Fix Ollama API URL normalization by removing trailing slashes (#6079) Co-authored-by: Nahim El Atmani <2959826+Naam@users.noreply.github.com> --- .../embedders/__tests__/ollama.spec.ts | 84 +++++++++++++++++++ src/services/code-index/embedders/ollama.ts | 7 +- 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/src/services/code-index/embedders/__tests__/ollama.spec.ts b/src/services/code-index/embedders/__tests__/ollama.spec.ts index ad95a18a3a..253158dd50 100644 --- a/src/services/code-index/embedders/__tests__/ollama.spec.ts +++ b/src/services/code-index/embedders/__tests__/ollama.spec.ts @@ -80,6 +80,90 @@ describe("CodeIndexOllamaEmbedder", () => { const embedderWithDefaults = new CodeIndexOllamaEmbedder({}) expect(embedderWithDefaults.embedderInfo.name).toBe("ollama") }) + + it("should normalize URLs with trailing slashes", async () => { + // Create embedder with URL that has a trailing slash + const embedderWithTrailingSlash = new CodeIndexOllamaEmbedder({ + ollamaBaseUrl: "http://localhost:11434/", + ollamaModelId: "nomic-embed-text", + }) + + // Mock successful /api/tags call to test the normalized URL + mockFetch.mockImplementationOnce(() => + Promise.resolve({ + ok: true, + status: 200, + json: () => Promise.resolve({ models: [{ name: "nomic-embed-text" }] }), + } as Response), + ) + + // Call a method that uses the baseUrl + await embedderWithTrailingSlash.validateConfiguration() + + // Verify the URL used in the fetch call doesn't have a trailing slash + expect(mockFetch).toHaveBeenCalledWith( + "http://localhost:11434/api/tags", + expect.objectContaining({ + method: "GET", + }), + ) + }) + + it("should not modify URLs without trailing slashes", async () => { + // Create embedder with URL that doesn't have a trailing slash + const embedderWithoutTrailingSlash = new CodeIndexOllamaEmbedder({ + ollamaBaseUrl: "http://localhost:11434", + ollamaModelId: "nomic-embed-text", + }) + + // Mock successful /api/tags call + mockFetch.mockImplementationOnce(() => + Promise.resolve({ + ok: true, + status: 200, + json: () => Promise.resolve({ models: [{ name: "nomic-embed-text" }] }), + } as Response), + ) + + // Call a method that uses the baseUrl + await embedderWithoutTrailingSlash.validateConfiguration() + + // Verify the URL used in the fetch call is correct + expect(mockFetch).toHaveBeenCalledWith( + "http://localhost:11434/api/tags", + expect.objectContaining({ + method: "GET", + }), + ) + }) + + it("should handle multiple trailing slashes", async () => { + // Create embedder with URL that has multiple trailing slashes + const embedderWithMultipleTrailingSlashes = new CodeIndexOllamaEmbedder({ + ollamaBaseUrl: "http://localhost:11434///", + ollamaModelId: "nomic-embed-text", + }) + + // Mock successful /api/tags call + mockFetch.mockImplementationOnce(() => + Promise.resolve({ + ok: true, + status: 200, + json: () => Promise.resolve({ models: [{ name: "nomic-embed-text" }] }), + } as Response), + ) + + // Call a method that uses the baseUrl + await embedderWithMultipleTrailingSlashes.validateConfiguration() + + // Verify the URL used in the fetch call doesn't have trailing slashes + expect(mockFetch).toHaveBeenCalledWith( + "http://localhost:11434/api/tags", + expect.objectContaining({ + method: "GET", + }), + ) + }) }) describe("validateConfiguration", () => { diff --git a/src/services/code-index/embedders/ollama.ts b/src/services/code-index/embedders/ollama.ts index c160d39490..9688a15ff0 100644 --- a/src/services/code-index/embedders/ollama.ts +++ b/src/services/code-index/embedders/ollama.ts @@ -20,7 +20,12 @@ export class CodeIndexOllamaEmbedder implements IEmbedder { constructor(options: ApiHandlerOptions) { // Ensure ollamaBaseUrl and ollamaModelId exist on ApiHandlerOptions or add defaults - this.baseUrl = options.ollamaBaseUrl || "http://localhost:11434" + let baseUrl = options.ollamaBaseUrl || "http://localhost:11434" + + // Normalize the baseUrl by removing all trailing slashes + baseUrl = baseUrl.replace(/\/+$/, "") + + this.baseUrl = baseUrl this.defaultModelId = options.ollamaModelId || "nomic-embed-text:latest" }