From 8ca628a8725a0e1200bed37cae5af7773758944b Mon Sep 17 00:00:00 2001 From: "dayuan.jiang" Date: Thu, 11 Jun 2026 13:44:38 +0900 Subject: [PATCH] fix: merge env AI_MODELS_CONFIG with admin panel providers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, saving in the admin panel wrote a complete AI_MODELS_CONFIG into settings.json, which (by overlay precedence) replaced any config from .env or ai-models.json — admins lost their env-configured models. The panel no longer writes AI_MODELS_CONFIG. Instead its providers are merged with the env baseline at read time in loadRawServerModelsConfig, and panel credentials go to ADMIN_-prefixed env vars wired up via apiKeyEnv/baseUrlEnv so they never shadow standard vars. Env-based providers now appear read-only in the panel, name clashes are rejected, and a panel default overrides the env default. data/ is now gitignored. --- .gitignore | 3 + app/[lang]/admin/page.tsx | 88 ++++++++++++- app/api/admin/providers/route.ts | 21 ++- lib/admin/providers.ts | 173 +++++++++++++------------ lib/server-model-config.ts | 36 ++++- tests/unit/admin-providers.test.ts | 135 ++++++++++++++++--- tests/unit/server-model-config.test.ts | 12 +- 7 files changed, 359 insertions(+), 109 deletions(-) diff --git a/.gitignore b/.gitignore index 7427ecb..0e8010a 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,6 @@ ai-models.json # local backups *.bak .gstack/ + +# admin panel settings (contains secrets) +data/ diff --git a/app/[lang]/admin/page.tsx b/app/[lang]/admin/page.tsx index 6045be1..58c97ce 100644 --- a/app/[lang]/admin/page.tsx +++ b/app/[lang]/admin/page.tsx @@ -90,6 +90,14 @@ interface AdminProvider { isDefault?: boolean } +// Provider defined in AI_MODELS_CONFIG / ai-models.json — shown read-only +interface EnvProvider { + name: string + provider: ProviderName + models: string[] + isDefault: boolean +} + async function adminFetch(path: string, pw: string, init?: RequestInit) { const res = await fetch(getApiEndpoint(path), { ...init, @@ -726,11 +734,13 @@ function ProviderDetail({ function ModelsSection({ providers, + envProviders, disabled, password, onChange, }: { providers: AdminProvider[] + envProviders: EnvProvider[] disabled: boolean password: string onChange: (providers: AdminProvider[]) => void @@ -739,6 +749,7 @@ function ModelsSection({ providers[0]?.id ?? null, ) const selected = providers.find((p) => p.id === selectedId) + const selectedEnv = envProviders.find((p) => `env:${p.name}` === selectedId) const addProvider = (provider: ProviderName) => { const newProvider: AdminProvider = { @@ -774,12 +785,38 @@ function ModelsSection({ {/* Provider list */}
- {providers.length === 0 && ( + {providers.length === 0 && envProviders.length === 0 && (

Add a provider to offer server-side models to all users.

)} + {envProviders.map((p) => ( + + ))} {providers.map((p) => (