feat: multi-gateway profile support, provider management overhaul, and model settings tab

- Profile-aware proxy: inject API key from profile-specific .env, route requests via X-Hermes-Profile header
- Remove auth.json dependency: built-in providers use .env, custom providers use config.yaml
- Add allProviders field to available-models response with all hardcoded provider catalogs
- Add Models tab in Settings for editing provider API keys (built-in → .env, custom → config.yaml)
- Add PUT /api/config/providers/:poolKey for updating provider credentials
- ProviderFormModal uses backend allProviders for preset dropdown
- Gateway log format support: parse both agent and gateway log formats
- Add webui server.log to log viewer with log rotation at 3MB
- Fix provider delete loading state and OAuth provider cleanup
- Setup script: require Node.js 23+, auto-upgrade if version too low

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ekko
2026-04-19 20:59:25 +08:00
parent e7e4c386c3
commit 562261d13f
19 changed files with 635 additions and 276 deletions
+6 -1
View File
@@ -45,7 +45,12 @@ export function streamRunEvents(
) {
const baseUrl = getBaseUrlValue()
const token = getApiKey()
const url = `${baseUrl}/api/hermes/v1/runs/${runId}/events${token ? `?token=${encodeURIComponent(token)}` : ''}`
const profile = localStorage.getItem('hermes_active_profile_name')
const params = new URLSearchParams()
if (token) params.set('token', token)
if (profile && profile !== 'default') params.set('profile', profile)
const qs = params.toString()
const url = `${baseUrl}/api/hermes/v1/runs/${runId}/events${qs ? `?${qs}` : ''}`
let closed = false
const source = new EventSource(url)
+14
View File
@@ -29,12 +29,14 @@ export interface AvailableModelGroup {
label: string // display name (e.g. "zai", "subrouter.ai")
base_url: string
models: string[]
api_key: string
}
export interface AvailableModelsResponse {
default: string
default_provider: string
groups: AvailableModelGroup[]
allProviders: AvailableModelGroup[]
}
export interface CustomProvider {
@@ -85,3 +87,15 @@ export async function removeCustomProvider(name: string): Promise<void> {
method: 'DELETE',
})
}
export async function updateProvider(poolKey: string, data: {
name?: string
base_url?: string
api_key?: string
model?: string
}): Promise<void> {
await request(`/api/hermes/config/providers/${encodeURIComponent(poolKey)}`, {
method: 'PUT',
body: JSON.stringify(data),
})
}