Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ LLAMACPP_HOST=
MLX_HOST=
LMSTUDIO_HOST=

# Optional bearer tokens for local providers deployed behind --api-key
# (vllm-mlx, llama.cpp server, LM Studio with auth, or an authenticated
# Ollama reverse-proxy). Leave blank for unauthenticated local serving.
MLX_API_KEY=
LLAMACPP_API_KEY=
LMSTUDIO_API_KEY=
OLLAMA_API_KEY=

# Default per-request timeout in seconds. Applies to every provider.
MODEL_REQUEST_TIMEOUT_SECONDS=30

Expand Down
33 changes: 27 additions & 6 deletions lib/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,38 @@ function buildProviderBaseUrl(provider: ProviderName, envName: string): string {
}

function buildProviderApiKey(provider: ProviderName, envName: string): string | undefined {
if (provider !== "openrouter") {
return undefined;
if (provider === "openrouter") {
const apiKey = process.env.OPENROUTER_API_KEY?.trim();

if (!apiKey) {
throw new Error(`OPENROUTER_API_KEY is required when ${envName} includes an openrouter model.`);
}

return apiKey;
}

// Local OpenAI-compatible servers may be deployed behind a bearer token
// (e.g. vllm-mlx --api-key, llama.cpp server --api-key, LM Studio's auth
// toggle, an Ollama reverse-proxy with bearer auth). The key is optional;
// when unset the request goes out without an Authorization header, which
// is the default for unauthenticated local serving.
if (provider === "mlx") {
return process.env.MLX_API_KEY?.trim() || undefined;
}

if (provider === "llamacpp") {
return process.env.LLAMACPP_API_KEY?.trim() || undefined;
}

const apiKey = process.env.OPENROUTER_API_KEY?.trim();
if (provider === "lmstudio") {
return process.env.LMSTUDIO_API_KEY?.trim() || undefined;
}

if (!apiKey) {
throw new Error(`OPENROUTER_API_KEY is required when ${envName} includes an openrouter model.`);
if (provider === "ollama") {
return process.env.OLLAMA_API_KEY?.trim() || undefined;
}

return apiKey;
return undefined;
}

function parseProvider(rawProvider: string, index: number, envName: string): ProviderName {
Expand Down