feat(byok): add model selection to BYOK settings panel and overlay custom model on route resolution
Some checks failed
CI / Deploy production (on server) (push) Has been cancelled
CI / Lint, Unit Tests & Build (push) Has been cancelled

This commit is contained in:
Antigravity
2026-05-28 21:41:34 +00:00
parent 3b2570d981
commit 11a07adee7
3 changed files with 119 additions and 12 deletions

View File

@@ -25,6 +25,7 @@ async function resolveProviderForLane(
const cfg = { ...config };
const route = resolveAiRoute(lane, cfg);
let usedByok = false;
let byokModel: string | null = null;
if (billingUserId) {
const overlay = await applyByokToConfig(
@@ -34,17 +35,22 @@ async function resolveProviderForLane(
);
Object.assign(cfg, overlay.config);
usedByok = overlay.usedByok;
byokModel = overlay.model;
}
const resolvedModel = byokModel && byokModel.trim() !== '' ? byokModel : route.modelName;
const provider = getProviderInstance(
route.providerType as ProviderType,
cfg,
route.modelName,
resolvedModel,
route.embeddingModelName,
route.ollamaBaseUrl,
);
return { provider, usedByok, route };
const updatedRoute = { ...route, modelName: resolvedModel };
return { provider, usedByok, route: updatedRoute };
}
async function getChatProviderForBillingUser(

View File

@@ -51,12 +51,12 @@ export async function getActiveByokKey(userId: string, provider: string) {
export async function resolveByokApiKey(
userId: string,
providerType: string,
): Promise<{ plaintext: string; provider: string } | null> {
): Promise<{ plaintext: string; provider: string; model: string | null } | null> {
const row = await getActiveByokKey(userId, providerType);
if (!row) return null;
try {
const plaintext = await decryptApiKey(row.encryptedKey);
return { plaintext, provider: row.provider };
return { plaintext, provider: row.provider, model: row.model };
} catch (err) {
console.error('[byok] Failed to decrypt key for provider', providerType, err);
return null;
@@ -67,16 +67,17 @@ export async function applyByokToConfig(
billingUserId: string,
providerType: string,
config: Record<string, string>,
): Promise<{ config: Record<string, string>; usedByok: boolean }> {
): Promise<{ config: Record<string, string>; usedByok: boolean; model: string | null }> {
const byok = await resolveByokApiKey(billingUserId, providerType);
if (!byok) return { config, usedByok: false };
if (!byok) return { config, usedByok: false, model: null };
const { apiKeyConfigKey } = getProviderConfigKeys(providerType);
if (!apiKeyConfigKey) return { config, usedByok: false };
if (!apiKeyConfigKey) return { config, usedByok: false, model: null };
return {
config: { ...config, [apiKeyConfigKey]: byok.plaintext },
usedByok: true,
model: byok.model,
};
}