From e837500c6ffcc477222305fd9b952dc9e7a95db1 Mon Sep 17 00:00:00 2001 From: Dave Date: Wed, 16 Sep 2026 15:53:59 +0200 Subject: [PATCH] feat(ai): single point of provider selection --- src/lib/ai/index.ts | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/lib/ai/index.ts diff --git a/src/lib/ai/index.ts b/src/lib/ai/index.ts new file mode 100644 index 0000000..5a2c7ff --- /dev/null +++ b/src/lib/ai/index.ts @@ -0,0 +1,41 @@ +import "server-only"; + +import { loadAiSettings } from "@/lib/ai/settings"; +import { buildSystemPrompt } from "@/lib/ai/prompt"; +import { createAnthropicProvider } from "@/lib/ai/provider-anthropic"; +import { createOpenAiCompatibleProvider } from "@/lib/ai/provider-openai"; +import { AiError, type AiProvider } from "@/lib/ai/types"; + +/** + * The only module that decides which provider is active. + * + * Every consumer asks for `getProvider()` and gets the interface. Nothing else + * in the codebase should import an adapter directly — that is what keeps + * switching provider a settings change. + */ +export async function getProvider(): Promise { + const settings = await loadAiSettings(); + + if (!settings?.apiKey) { + throw new AiError("No AI provider is configured", false); + } + + if (settings.provider === "anthropic") { + return createAnthropicProvider(settings.apiKey, settings.model); + } + + return createOpenAiCompatibleProvider( + settings.apiKey, + settings.model, + settings.provider + ); +} + +/** The full system prompt for the current settings. */ +export async function getSystemPrompt(): Promise { + const settings = await loadAiSettings(); + return buildSystemPrompt(settings?.systemPromptExtra ?? ""); +} + +export { AiError }; +export type { AiProvider, CompletionRequest, CompletionResult } from "@/lib/ai/types"; \ No newline at end of file