mirror of
https://github.com/giancarloerra/socraticode.git
synced 2026-07-03 14:05:21 +02:00
252 lines
8.6 KiB
TypeScript
252 lines
8.6 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-only
|
|
// Copyright (C) 2026 Giancarlo Erra - Altaire Limited
|
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
import {
|
|
getEmbeddingConfig,
|
|
loadEmbeddingConfig,
|
|
resetEmbeddingConfig,
|
|
} from "../../src/services/embedding-config.js";
|
|
|
|
describe("embedding-config", () => {
|
|
const originalEnv = { ...process.env };
|
|
|
|
beforeEach(() => {
|
|
resetEmbeddingConfig();
|
|
// Clear all embedding-related env vars
|
|
delete process.env.EMBEDDING_PROVIDER;
|
|
delete process.env.OLLAMA_MODE;
|
|
delete process.env.OLLAMA_URL;
|
|
delete process.env.EMBEDDING_MODEL;
|
|
delete process.env.EMBEDDING_DIMENSIONS;
|
|
delete process.env.EMBEDDING_CONTEXT_LENGTH;
|
|
delete process.env.OLLAMA_API_KEY;
|
|
delete process.env.OPENAI_API_KEY;
|
|
delete process.env.GOOGLE_API_KEY;
|
|
});
|
|
|
|
afterEach(() => {
|
|
resetEmbeddingConfig();
|
|
// Restore original env
|
|
process.env = { ...originalEnv };
|
|
});
|
|
|
|
describe("defaults (no env vars)", () => {
|
|
it("defaults to ollama provider", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingProvider).toBe("ollama");
|
|
});
|
|
|
|
it("defaults to auto mode", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaMode).toBe("auto");
|
|
});
|
|
|
|
it("defaults URL to localhost:11434 in auto mode", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaUrl).toBe("http://localhost:11434");
|
|
});
|
|
|
|
it("defaults model to nomic-embed-text", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingModel).toBe("nomic-embed-text");
|
|
});
|
|
|
|
it("defaults dimensions to 768", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingDimensions).toBe(768);
|
|
});
|
|
|
|
it("has no API key by default", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaApiKey).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("docker mode", () => {
|
|
it("uses docker URL default when OLLAMA_MODE=docker", () => {
|
|
process.env.OLLAMA_MODE = "docker";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaMode).toBe("docker");
|
|
expect(config.ollamaUrl).toBe("http://localhost:11435");
|
|
});
|
|
|
|
it("allows overriding URL in docker mode", () => {
|
|
process.env.OLLAMA_MODE = "docker";
|
|
process.env.OLLAMA_URL = "http://custom:9999";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaUrl).toBe("http://custom:9999");
|
|
});
|
|
});
|
|
|
|
describe("external mode", () => {
|
|
it("uses external URL default when OLLAMA_MODE=external", () => {
|
|
process.env.OLLAMA_MODE = "external";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaMode).toBe("external");
|
|
expect(config.ollamaUrl).toBe("http://localhost:11434");
|
|
});
|
|
|
|
it("allows overriding URL in external mode", () => {
|
|
process.env.OLLAMA_MODE = "external";
|
|
process.env.OLLAMA_URL = "http://gpu-server:11434";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaUrl).toBe("http://gpu-server:11434");
|
|
});
|
|
});
|
|
|
|
describe("model and dimensions overrides", () => {
|
|
it("allows custom model", () => {
|
|
process.env.EMBEDDING_MODEL = "mxbai-embed-large";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingModel).toBe("mxbai-embed-large");
|
|
});
|
|
|
|
it("allows custom dimensions", () => {
|
|
process.env.EMBEDDING_DIMENSIONS = "1024";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingDimensions).toBe(1024);
|
|
});
|
|
|
|
it("parses dimensions as integer", () => {
|
|
process.env.EMBEDDING_DIMENSIONS = "512";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingDimensions).toBe(512);
|
|
expect(typeof config.embeddingDimensions).toBe("number");
|
|
});
|
|
});
|
|
|
|
describe("API key", () => {
|
|
it("reads OLLAMA_API_KEY when set", () => {
|
|
process.env.OLLAMA_API_KEY = "test-key-123";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaApiKey).toBe("test-key-123");
|
|
});
|
|
|
|
it("is undefined when not set", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.ollamaApiKey).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe("invalid mode", () => {
|
|
it("throws for invalid OLLAMA_MODE", () => {
|
|
process.env.OLLAMA_MODE = "invalid";
|
|
expect(() => loadEmbeddingConfig()).toThrow(
|
|
'Invalid OLLAMA_MODE: "invalid". Must be "docker", "external", or "auto".',
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("singleton behavior", () => {
|
|
it("caches config after first load", () => {
|
|
const first = loadEmbeddingConfig();
|
|
// Change env — should NOT affect cached config
|
|
process.env.OLLAMA_MODE = "external";
|
|
const second = loadEmbeddingConfig();
|
|
expect(second).toBe(first); // same reference
|
|
expect(second.ollamaMode).toBe("auto");
|
|
});
|
|
|
|
it("getEmbeddingConfig returns same as loadEmbeddingConfig", () => {
|
|
const loaded = loadEmbeddingConfig();
|
|
const got = getEmbeddingConfig();
|
|
expect(got).toBe(loaded);
|
|
});
|
|
|
|
it("resetEmbeddingConfig clears cache", () => {
|
|
const first = loadEmbeddingConfig();
|
|
expect(first.ollamaMode).toBe("auto");
|
|
|
|
resetEmbeddingConfig();
|
|
process.env.OLLAMA_MODE = "external";
|
|
const second = loadEmbeddingConfig();
|
|
expect(second.ollamaMode).toBe("external");
|
|
expect(second).not.toBe(first);
|
|
});
|
|
});
|
|
|
|
describe("full external config", () => {
|
|
it("handles complete external config with all options", () => {
|
|
process.env.OLLAMA_MODE = "external";
|
|
process.env.OLLAMA_URL = "http://remote-gpu:11434";
|
|
process.env.EMBEDDING_MODEL = "mxbai-embed-large";
|
|
process.env.EMBEDDING_DIMENSIONS = "1024";
|
|
process.env.OLLAMA_API_KEY = "secret";
|
|
|
|
const config = loadEmbeddingConfig();
|
|
expect(config).toEqual({
|
|
embeddingProvider: "ollama",
|
|
ollamaMode: "external",
|
|
ollamaUrl: "http://remote-gpu:11434",
|
|
embeddingModel: "mxbai-embed-large",
|
|
embeddingDimensions: 1024,
|
|
embeddingContextLength: 512,
|
|
ollamaApiKey: "secret",
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("embedding provider selection", () => {
|
|
it("defaults to ollama when EMBEDDING_PROVIDER is not set", () => {
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingProvider).toBe("ollama");
|
|
expect(config.embeddingModel).toBe("nomic-embed-text");
|
|
expect(config.embeddingDimensions).toBe(768);
|
|
});
|
|
|
|
it("selects openai provider with correct defaults", () => {
|
|
process.env.EMBEDDING_PROVIDER = "openai";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingProvider).toBe("openai");
|
|
expect(config.embeddingModel).toBe("text-embedding-3-small");
|
|
expect(config.embeddingDimensions).toBe(1536);
|
|
expect(config.embeddingContextLength).toBe(8191);
|
|
});
|
|
|
|
it("selects google provider with correct defaults", () => {
|
|
process.env.EMBEDDING_PROVIDER = "google";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingProvider).toBe("google");
|
|
expect(config.embeddingModel).toBe("gemini-embedding-001");
|
|
expect(config.embeddingDimensions).toBe(3072);
|
|
expect(config.embeddingContextLength).toBe(2048);
|
|
});
|
|
|
|
it("throws for invalid EMBEDDING_PROVIDER", () => {
|
|
process.env.EMBEDDING_PROVIDER = "anthropic";
|
|
expect(() => loadEmbeddingConfig()).toThrow(
|
|
'Invalid EMBEDDING_PROVIDER: "anthropic". Must be "ollama", "openai", or "google".',
|
|
);
|
|
});
|
|
|
|
it("allows overriding model for openai provider", () => {
|
|
process.env.EMBEDDING_PROVIDER = "openai";
|
|
process.env.EMBEDDING_MODEL = "text-embedding-3-large";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingModel).toBe("text-embedding-3-large");
|
|
expect(config.embeddingContextLength).toBe(8191);
|
|
});
|
|
|
|
it("allows overriding dimensions for openai provider", () => {
|
|
process.env.EMBEDDING_PROVIDER = "openai";
|
|
process.env.EMBEDDING_DIMENSIONS = "256";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingDimensions).toBe(256);
|
|
});
|
|
|
|
it("uses context length for unknown model", () => {
|
|
process.env.EMBEDDING_PROVIDER = "openai";
|
|
process.env.EMBEDDING_MODEL = "custom-embed-model";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingContextLength).toBe(0);
|
|
});
|
|
|
|
it("allows explicit context length override for any provider", () => {
|
|
process.env.EMBEDDING_PROVIDER = "google";
|
|
process.env.EMBEDDING_CONTEXT_LENGTH = "4096";
|
|
const config = loadEmbeddingConfig();
|
|
expect(config.embeddingContextLength).toBe(4096);
|
|
});
|
|
});
|
|
});
|