diff --git a/packages/server/src/controllers/hermes/models.ts b/packages/server/src/controllers/hermes/models.ts index 11be2d5..a3f09f5 100644 --- a/packages/server/src/controllers/hermes/models.ts +++ b/packages/server/src/controllers/hermes/models.ts @@ -72,11 +72,15 @@ export async function getAvailable(ctx: any) { if (!cp.base_url) return null const providerKey = `custom:${cp.name.trim().toLowerCase().replace(/ /g, '-')}` const baseUrl = cp.base_url.replace(/\/+$/, '') - let models = [cp.model] + const bareKey = cp.name.trim().toLowerCase().replace(/ /g, '-') + const builtinPreset = PROVIDER_PRESETS.find(p => p.value === bareKey) + let models = builtinPreset?.models?.length ? [...builtinPreset.models] : [cp.model] if (cp.api_key) { try { const fetched = await fetchProviderModels(baseUrl, cp.api_key); if (fetched.length > 0) models = fetched } catch { } } - return { providerKey, label: cp.name, base_url: baseUrl, models, api_key: cp.api_key || '' } + const label = builtinPreset?.label || cp.name + const presetBaseUrl = builtinPreset?.base_url || '' + return { providerKey, label, base_url: presetBaseUrl || baseUrl, models, api_key: cp.api_key || '' } }), ) diff --git a/packages/server/src/controllers/hermes/providers.ts b/packages/server/src/controllers/hermes/providers.ts index cfa8008..dc59e10 100644 --- a/packages/server/src/controllers/hermes/providers.ts +++ b/packages/server/src/controllers/hermes/providers.ts @@ -9,6 +9,7 @@ export async function create(ctx: any) { const { name, base_url, api_key, model, providerKey } = ctx.request.body as { name: string; base_url: string; api_key: string; model: string; providerKey?: string | null } + console.log(name, base_url, api_key, model, providerKey) if (!name || !base_url || !model) { ctx.status = 400; ctx.body = { error: 'Missing name, base_url, or model' }; return } @@ -18,31 +19,48 @@ export async function create(ctx: any) { try { const poolKey = providerKey || `custom:${name.trim().toLowerCase().replace(/ /g, '-')}` const isBuiltin = poolKey in PROVIDER_ENV_MAP + const config = await readConfigYaml() + if (typeof config.model !== 'object' || config.model === null) { config.model = {} } if (!isBuiltin) { - const config = await readConfigYaml() if (!Array.isArray(config.custom_providers)) { config.custom_providers = [] } const existing = (config.custom_providers as any[]).find( - (e: any) => `custom:${e.name.trim().toLowerCase().replace(/ /g, '-')}` === poolKey + (e: any) => `custom:${e.name}` === poolKey ) if (existing) { existing.base_url = base_url existing.api_key = api_key existing.model = model } else { - config.custom_providers.push({ name, base_url, api_key, model }) + config.custom_providers.push({ name: name.trim().toLowerCase().replace(/ /g, '-'), base_url, api_key, model }) + } + config.model.default = model + config.model.provider = poolKey + } else { + console.log(PROVIDER_ENV_MAP[poolKey]) + if (PROVIDER_ENV_MAP[poolKey].api_key_env) { + await saveEnvValue(PROVIDER_ENV_MAP[poolKey].api_key_env, api_key) + if (PROVIDER_ENV_MAP[poolKey].base_url_env) { await saveEnvValue(PROVIDER_ENV_MAP[poolKey].base_url_env, base_url) } + config.model.default = model + config.model.provider = poolKey + } else { + if (!Array.isArray(config.custom_providers)) { config.custom_providers = [] } + const existing = (config.custom_providers as any[]).find( + (e: any) => `custom:${e.name}` === `custom:${poolKey}` + ) + if (existing) { + existing.base_url = base_url + existing.api_key = api_key + existing.model = model + } else { + config.custom_providers.push({ name: poolKey, base_url, api_key, model }) + } + config.model.default = model + config.model.provider = `custom:${poolKey}` } - await writeConfigYaml(config) } - const envMapping = isBuiltin ? (PROVIDER_ENV_MAP[poolKey] || PROVIDER_ENV_MAP[providerKey || '']) : null - if (envMapping) { - await saveEnvValue(envMapping.api_key_env, api_key) - if (envMapping.base_url_env) { await saveEnvValue(envMapping.base_url_env, base_url) } - } - const config2 = await readConfigYaml() - if (typeof config2.model !== 'object' || config2.model === null) { config2.model = {} } - config2.model.default = model - config2.model.provider = poolKey - await writeConfigYaml(config2) + delete config.model.base_url + delete config.model.api_key + await writeConfigYaml(config) try { await hermesCli.restartGateway() } catch (e: any) { logger.error(e, 'Gateway restart failed') } ctx.body = { success: true } } catch (err: any) { @@ -95,8 +113,8 @@ export async function remove(ctx: any) { if (isCustom) { const idx = Array.isArray(config.custom_providers) ? (config.custom_providers as any[]).findIndex((e: any) => { - return `custom:${e.name.trim().toLowerCase().replace(/ /g, '-')}` === poolKey - }) + return `custom:${e.name.trim().toLowerCase().replace(/ /g, '-')}` === poolKey + }) : -1 if (idx === -1) { ctx.status = 404; ctx.body = { error: `Custom provider "${poolKey}" not found` }; return @@ -123,15 +141,21 @@ export async function remove(ctx: any) { if (currentProvider === poolKey) { const freshConfig = await readConfigYaml() const remaining = Array.isArray(freshConfig.custom_providers) ? freshConfig.custom_providers as any[] : [] - const fallbackCp = remaining[0] - if (fallbackCp) { + if (remaining.length > 0) { + const fallbackCp = remaining[0] const fallbackKey = `custom:${fallbackCp.name.trim().toLowerCase().replace(/ /g, '-')}` if (typeof freshConfig.model !== 'object' || freshConfig.model === null) { freshConfig.model = {} } freshConfig.model.default = fallbackCp.model freshConfig.model.provider = fallbackKey + delete freshConfig.model.base_url + delete freshConfig.model.api_key + await writeConfigYaml(freshConfig) + } else { + freshConfig.model = {} await writeConfigYaml(freshConfig) } } + try { await hermesCli.restartGateway() } catch (e: any) { logger.error(e, 'Gateway restart failed') } ctx.body = { success: true } } catch (err: any) { ctx.status = 500; ctx.body = { error: err.message } diff --git a/packages/server/src/services/config-helpers.ts b/packages/server/src/services/config-helpers.ts index d3fddb4..f4d5247 100644 --- a/packages/server/src/services/config-helpers.ts +++ b/packages/server/src/services/config-helpers.ts @@ -9,6 +9,7 @@ import { logger } from './logger' // --- Provider env var mapping (from hermes providers.py HERMES_OVERLAYS + config.py) --- export const PROVIDER_ENV_MAP: Record = { openrouter: { api_key_env: 'OPENROUTER_API_KEY', base_url_env: '' }, + 'glm-coding-plan': { api_key_env: '', base_url_env: '' }, zai: { api_key_env: 'GLM_API_KEY', base_url_env: '' }, 'kimi-coding-cn': { api_key_env: 'KIMI_CN_API_KEY', base_url_env: '' }, moonshot: { api_key_env: 'MOONSHOT_API_KEY', base_url_env: '' }, diff --git a/packages/server/src/shared/providers.ts b/packages/server/src/shared/providers.ts index 4dd8a68..88e1c61 100644 --- a/packages/server/src/shared/providers.ts +++ b/packages/server/src/shared/providers.ts @@ -59,8 +59,8 @@ export const PROVIDER_PRESETS: ProviderPreset[] = [ models: ['glm-5.1', 'glm-5', 'glm-5v-turbo', 'glm-5-turbo', 'glm-4.7', 'glm-4.5', 'glm-4.5-flash'], }, { - label: 'GLMCodingPlan', - value: 'glm', + label: 'GLM-Coding-Plan', + value: 'glm-coding-plan', builtin: true, base_url: 'https://api.z.ai/api/anthropic', models: ['glm-5.1', 'glm-5', 'glm-5-turbo', 'glm-4.7', 'glm-4.5', 'glm-4.5-flash'],