refactor!(llm): Remove bootstrapper in favor of setup-provider

This commit is contained in:
Tom Pike
2026-07-16 22:21:59 +05:30
committed by Aditya Gupta
parent 250bb87a8d
commit 61ea9fe237
11 changed files with 398 additions and 255 deletions

View File

@@ -0,0 +1,126 @@
import { describe, test, expect, beforeEach, afterEach } from "vitest";
import { execSync } from "child_process";
import fs from "fs";
import path from "path";
import Database from "better-sqlite3";
describe("setup-provider CLI Tool Tests", () => {
let tempDbPath: string;
let scriptPath: string;
beforeEach(() => {
// Generate a unique temp database path
tempDbPath = path.resolve(
process.cwd(),
`test-cli-${Date.now()}-${Math.random().toString(36).substring(2)}.db`,
);
scriptPath = path.resolve(
process.cwd(),
"packages/llm/dist/bin/setup-provider.js",
);
});
afterEach(() => {
if (fs.existsSync(tempDbPath)) {
try {
fs.unlinkSync(tempDbPath);
} catch {
// ignore
}
}
});
test("prints help message when --help or -h is passed", () => {
const stdout = execSync(`node ${scriptPath} --help`).toString();
expect(stdout).toContain("Usage:");
expect(stdout).toContain("Options:");
expect(stdout).toContain("Registered Providers:");
});
test("creates a provider instance successfully via CLI flags", () => {
const cmd = `node ${scriptPath} --provider google-genai --key mock-key-abc --name "Test Gemini" --model "gemini-2.5-flash"`;
const stdout = execSync(cmd, {
env: { ...process.env, OMNIA_DB_PATH: tempDbPath },
}).toString();
expect(stdout).toContain("Successfully created provider instance:");
expect(stdout).toContain("Test Gemini");
expect(stdout).toContain("google-genai");
expect(stdout).toContain("mock-key-abc");
// Read the SQLite db directly to verify
const db = new Database(tempDbPath);
const rows = db.prepare("SELECT * FROM provider_instances").all() as {
name: string;
providerName: string;
apiKey: string;
modelName: string;
isActive: number;
}[];
expect(rows.length).toBe(1);
expect(rows[0].name).toBe("Test Gemini");
expect(rows[0].providerName).toBe("google-genai");
expect(rows[0].apiKey).toBe("mock-key-abc");
expect(rows[0].modelName).toBe("gemini-2.5-flash");
expect(rows[0].isActive).toBe(1);
db.close();
});
test("fails when required key is missing and env var is not set", () => {
let error: { status?: number; stderr?: Buffer } | undefined;
try {
execSync(`node ${scriptPath} --provider google-genai`, {
env: { ...process.env, OMNIA_DB_PATH: tempDbPath, GOOGLE_API_KEY: "" },
stdio: "pipe",
});
} catch (e) {
error = e as { status?: number; stderr?: Buffer };
}
expect(error).toBeDefined();
expect(error?.status).toBe(1);
expect(error?.stderr?.toString()).toContain("Error: API Key is required");
});
test("seeds from environment variables when using --all", () => {
const cmd = `node ${scriptPath} --all`;
const stdout = execSync(cmd, {
env: {
...process.env,
OMNIA_DB_PATH: tempDbPath,
GOOGLE_API_KEY: "mock-google-key-all",
OPENAI_API_KEY: "",
ANTHROPIC_API_KEY: "",
GROQ_API_KEY: "",
DEEPSEEK_API_KEY: "",
OPENROUTER_API_KEY: "",
},
}).toString();
expect(stdout).toContain(
"Created generative instance: Google Gemini (CLI)",
);
expect(stdout).toContain(
"Created embedding instance: Google Gemini Embed (CLI)",
);
const db = new Database(tempDbPath);
const rows = db.prepare("SELECT * FROM provider_instances").all() as {
type: string;
apiKey: string;
modelName: string;
}[];
// Should have both generative and embedding instances
expect(rows.length).toBe(2);
const gen = rows.find((r) => r.type === "generative");
const embed = rows.find((r) => r.type === "embedding");
expect(gen).toBeDefined();
expect(gen?.apiKey).toBe("mock-google-key-all");
expect(gen?.modelName).toBe("gemini-2.5-flash");
expect(embed).toBeDefined();
expect(embed?.apiKey).toBe("mock-google-key-all");
expect(embed?.modelName).toBe("gemini-embedding-001");
db.close();
});
});

View File

@@ -49,47 +49,10 @@ describe("ProviderManager Bootstrapping & CRUD Unit Tests", () => {
}
});
test("auto-bootstraps all environment-variable providers when database is empty", () => {
test("returns empty list when database is empty and no auto-bootstraps", () => {
process.env.GOOGLE_API_KEY = "mock-google-key";
process.env.OPENROUTER_API_KEY = "mock-openrouter-key";
process.env.ANTHROPIC_API_KEY = "mock-anthropic-key";
process.env.OPENAI_API_KEY = "mock-openai-key";
process.env.GROQ_API_KEY = "mock-groq-key";
process.env.DEEPSEEK_API_KEY = "mock-deepseek-key";
const list = ProviderManager.list();
const providers = list.map((p) => p.providerName);
expect(providers).toContain("google-genai");
expect(providers).toContain("openrouter");
expect(providers).toContain("anthropic");
expect(providers).toContain("openai");
expect(providers).toContain("groq");
expect(providers).toContain("deepseek");
// Gemini should have both generative + embedding (2 entries)
const geminiEntries = list.filter((p) => p.providerName === "google-genai");
expect(geminiEntries.length).toBe(2);
expect(geminiEntries.some((p) => p.type === "generative")).toBe(true);
expect(geminiEntries.some((p) => p.type === "embedding")).toBe(true);
// OpenAI should have both generative + embedding (2 entries)
const openaiEntries = list.filter((p) => p.providerName === "openai");
expect(openaiEntries.length).toBe(2);
expect(openaiEntries.some((p) => p.type === "generative")).toBe(true);
expect(openaiEntries.some((p) => p.type === "embedding")).toBe(true);
// First generative provider inserted should be active
const activeGenerative = list.filter(
(p) => p.type === "generative" && p.isActive,
);
expect(activeGenerative.length).toBe(1);
// First embedding provider inserted should be active
const activeEmbedding = list.filter(
(p) => p.type === "embedding" && p.isActive,
);
expect(activeEmbedding.length).toBe(1);
expect(list.length).toBe(0);
});
test("getActive returns null when no providers exist and no env vars", () => {
@@ -99,19 +62,10 @@ describe("ProviderManager Bootstrapping & CRUD Unit Tests", () => {
expect(activeEmbed).toBeNull();
});
test("getActive falls back to env var when DB operations fail or return null", () => {
test("getActive returns null when DB is empty", () => {
process.env.GOOGLE_API_KEY = "mock-google-key-123";
// DB is empty, getActive should bootstrap and find or create from env
const active = ProviderManager.getActive("generative");
expect(active).not.toBeNull();
expect(active?.providerName).toBe("google-genai");
expect(active?.apiKey).toBe("mock-google-key-123");
expect(active?.type).toBe("generative");
const activeEmbed = ProviderManager.getActive("embedding");
expect(activeEmbed).not.toBeNull();
expect(activeEmbed?.providerName).toBe("google-genai");
expect(activeEmbed?.type).toBe("embedding");
expect(active).toBeNull();
});
test("getActive returns first instance of type when none is active", () => {
@@ -250,20 +204,25 @@ describe("ProviderManager Bootstrapping & CRUD Unit Tests", () => {
expect(updated?.modelName).toBe("gpt-4o-mini");
expect(updated?.maxContext).toBe(64000);
});
test("treats bootstrapped instances as normal provider instances (editable and deletable)", () => {
process.env.GOOGLE_API_KEY = "mock-google-key-123";
test("treats created instances as normal provider instances (editable and deletable)", () => {
const inst = ProviderManager.create(
"Google Gemini (Env)",
"google-genai",
"mock-google-key-123",
"gemini-2.5-flash",
"generative",
);
// Trigger bootstrap
const list = ProviderManager.list();
expect(list.length).toBe(2);
const bootstrapped = list.find((p) => p.name === "Google Gemini (Env)");
expect(bootstrapped).toBeDefined();
if (!bootstrapped) return;
expect(bootstrapped.isActive).toBe(true);
expect(list.length).toBe(1);
const created = list.find((p) => p.id === inst.id);
expect(created).toBeDefined();
if (!created) return;
expect(created.isActive).toBe(true);
// Edit name and key
ProviderManager.update(
bootstrapped.id,
created.id,
"My Gemini Key",
"google-genai",
"new-secret-key",
@@ -271,8 +230,8 @@ describe("ProviderManager Bootstrapping & CRUD Unit Tests", () => {
);
const listAfterUpdate = ProviderManager.list();
expect(listAfterUpdate.length).toBe(2);
const updated = listAfterUpdate.find((p) => p.id === bootstrapped.id);
expect(listAfterUpdate.length).toBe(1);
const updated = listAfterUpdate.find((p) => p.id === created.id);
expect(updated).toBeDefined();
if (!updated) return;
expect(updated.name).toBe("My Gemini Key");
@@ -280,8 +239,8 @@ describe("ProviderManager Bootstrapping & CRUD Unit Tests", () => {
expect(updated.modelName).toBe("gemini-2.5-pro");
// Delete instance
ProviderManager.delete(bootstrapped.id);
ProviderManager.delete(created.id);
const listAfterDelete = ProviderManager.list();
expect(listAfterDelete.length).toBe(1);
expect(listAfterDelete.length).toBe(0);
});
});