Feat/bankr provider (#888)

* feat(provider): add Bankr LLM Gateway support

Add Bankr as an OpenAI-compatible provider preset with dedicated env vars:
- BNKR_API_KEY, BANKR_BASE_URL, BANKR_MODEL
- Uses X-API-Key header instead of Authorization Bearer
- Base URL: https://llm.bankr.bot/v1
- Default model: claude-opus-4.6

Changes:
- Add 'bankr' to VALID_PROVIDERS and provider flag handling
- Add buildBankrProfileEnv() with env key registration
- Add Bankr detection in startup screen and provider discovery
- Map Bankr env vars to OpenAI-compatible vars in shim
- Add Bankr preset to ProviderManager (alphabetical order)
- Update PRESET_ORDER test to include Bankr

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

* fixup(provider): address Bankr PR review feedback

1. Map BNKR_API_KEY → OPENAI_API_KEY in providerFlag.ts so
   --provider bankr works with BNKR_API_KEY in non-interactive startup.

2. Remove unconditional BANKR_MODEL read from model.ts; it maps to
   OPENAI_MODEL via providerFlag.ts and openaiShim.ts, preventing
   cross-provider leakage.

3. Use X-API-Key for Bankr model discovery in openaiModelDiscovery.ts
   and providerDiscovery.ts, matching chat request auth.

Co-Authored-By: OpenClaude <openclaude@gitlawb.com>

---------

Co-authored-by: OpenClaude <openclaude@gitlawb.com>
This commit is contained in:
Kevin Codex
2026-04-24 23:03:45 +08:00
committed by GitHub
parent 5a21d05741
commit 64b1014b9a
10 changed files with 130 additions and 6 deletions

View File

@@ -35,6 +35,7 @@ export type ProviderPreset =
| 'custom'
| 'nvidia-nim'
| 'minimax'
| 'bankr'
| 'atomic-chat'
export type ProviderProfileInput = {
@@ -297,6 +298,15 @@ export function getProviderPresetDefaults(
apiKey: '',
requiresApiKey: false,
}
case 'bankr':
return {
provider: 'openai',
name: 'Bankr',
baseUrl: 'https://llm.bankr.bot/v1',
model: process.env.BANKR_MODEL ?? 'claude-opus-4.6',
apiKey: process.env.BNKR_API_KEY ?? '',
requiresApiKey: true,
}
case 'ollama':
default:
return {
@@ -481,7 +491,11 @@ function isProcessEnvAlignedWithProfile(
sameOptionalEnvValue(processEnv.OPENAI_BASE_URL, profile.baseUrl) &&
sameOptionalEnvValue(processEnv.OPENAI_MODEL, getPrimaryModel(profile.model)) &&
(!includeApiKey ||
sameOptionalEnvValue(processEnv.OPENAI_API_KEY, profile.apiKey))
sameOptionalEnvValue(processEnv.OPENAI_API_KEY, profile.apiKey)) &&
(profile.baseUrl?.toLowerCase().includes('bankr')
? !includeApiKey ||
sameOptionalEnvValue(processEnv.BNKR_API_KEY, profile.apiKey)
: true)
)
}
@@ -534,6 +548,9 @@ export function clearProviderProfileEnvFromProcessEnv(
delete processEnv.MINIMAX_API_KEY
delete processEnv.NVIDIA_API_KEY
delete processEnv.NVIDIA_NIM
delete processEnv.BANKR_BASE_URL
delete processEnv.BNKR_API_KEY
delete processEnv.BANKR_MODEL
}
export function applyProviderProfileToProcessEnv(profile: ProviderProfile): void {
@@ -606,6 +623,9 @@ export function applyProviderProfileToProcessEnv(profile: ProviderProfile): void
if (baseUrl.includes('nvidia') || baseUrl.includes('integrate.api.nvidia')) {
process.env.NVIDIA_API_KEY = profile.apiKey
}
if (baseUrl.includes('bankr')) {
process.env.BNKR_API_KEY = profile.apiKey
}
} else {
delete process.env.OPENAI_API_KEY
}
@@ -860,6 +880,9 @@ function buildOpenAICompatibleStartupEnv(
}
if (activeProfile.apiKey) {
env.OPENAI_API_KEY = activeProfile.apiKey
if (activeProfile.baseUrl?.toLowerCase().includes('bankr')) {
env.BNKR_API_KEY = activeProfile.apiKey
}
} else {
delete env.OPENAI_API_KEY
}