mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-21 10:22:18 +00:00
feat(desktop): Keys tab groups by backend provider identity
buildProviderKeyGroups now groups provider env vars by the backend-supplied provider/provider_label (from the unified catalog — the same identity hermes model uses), falling back to the desktop PROVIDER_GROUPS prefix match only when the backend gives no hint. A provider the backend tags now always renders its own Keys card, even with no hand-maintained PROVIDER_GROUPS prefix row — PROVIDER_GROUPS is demoted to a presentation overlay (priority/blurb/docs). Adds provider/provider_label to EnvVarInfo. New vitest asserts a backend-tagged provider with no prefix row still renders a card.
This commit is contained in:
parent
60dfa0f31b
commit
6cb04be779
3 changed files with 50 additions and 3 deletions
|
|
@ -97,4 +97,31 @@ describe('ProvidersSettings', () => {
|
|||
expect(screen.queryByRole('button', { name: 'Remove Qwen Code' })).toBeNull()
|
||||
expect(screen.getByText(/managed by its own CLI/)).toBeTruthy()
|
||||
})
|
||||
|
||||
it('renders a Keys card for a backend-tagged provider with no PROVIDER_GROUPS prefix', async () => {
|
||||
// A provider the backend catalog tags (provider/provider_label) but that has
|
||||
// no desktop PROVIDER_GROUPS prefix row must still render its own card —
|
||||
// this is the GUI/CLI drift fix: membership comes from the backend, not
|
||||
// from the hand-maintained prefix list.
|
||||
getEnvVars.mockResolvedValue({
|
||||
WIDGETAI_API_KEY: {
|
||||
advanced: false,
|
||||
category: 'provider',
|
||||
description: 'WidgetAI direct API',
|
||||
is_password: true,
|
||||
is_set: false,
|
||||
provider: 'widgetai',
|
||||
provider_label: 'WidgetAI',
|
||||
redacted_value: null,
|
||||
tools: [],
|
||||
url: 'https://widgetai.example/keys'
|
||||
}
|
||||
})
|
||||
listOAuthProviders.mockResolvedValue({ providers: [] })
|
||||
|
||||
const { ProvidersSettings } = await import('./providers-settings')
|
||||
render(<ProvidersSettings onClose={vi.fn()} onViewChange={vi.fn()} view="keys" />)
|
||||
|
||||
expect(await screen.findByText('WidgetAI')).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -45,8 +45,17 @@ export const PROVIDER_VIEWS = ['accounts', 'keys'] as const
|
|||
export type ProviderView = (typeof PROVIDER_VIEWS)[number]
|
||||
|
||||
// Group the env catalog by provider — one ListRow per vendor plus optional
|
||||
// advanced overrides (base URL, region, etc.). Groups without a key field and
|
||||
// the "Other" bucket are skipped.
|
||||
// advanced overrides (base URL, region, etc.). Groups without a key field are
|
||||
// skipped.
|
||||
//
|
||||
// Grouping key precedence:
|
||||
// 1. Backend `provider_label` / `provider` (from the unified provider catalog
|
||||
// in hermes_cli/provider_catalog.py) — the SAME provider identity
|
||||
// `hermes model` uses. This is authoritative: a provider tagged by the
|
||||
// backend always renders a card, even with no PROVIDER_GROUPS row.
|
||||
// 2. Desktop prefix match (`providerGroup`) — legacy fallback for provider
|
||||
// env vars that predate the backend tagging.
|
||||
// Only entries that resolve to neither (the "Other" bucket) are skipped.
|
||||
function buildProviderKeyGroups(vars: Record<string, EnvVarInfo>): ProviderKeyGroup[] {
|
||||
const buckets = new Map<string, [string, EnvVarInfo][]>()
|
||||
|
||||
|
|
@ -55,7 +64,9 @@ function buildProviderKeyGroups(vars: Record<string, EnvVarInfo>): ProviderKeyGr
|
|||
continue
|
||||
}
|
||||
|
||||
const name = providerGroup(key)
|
||||
// Prefer the backend-supplied provider label/id so the Keys tab groups by
|
||||
// the same identity the CLI picker uses; fall back to the prefix guess.
|
||||
const name = info.provider_label?.trim() || info.provider?.trim() || providerGroup(key)
|
||||
|
||||
if (name === 'Other') {
|
||||
continue
|
||||
|
|
@ -73,6 +84,9 @@ function buildProviderKeyGroups(vars: Record<string, EnvVarInfo>): ProviderKeyGr
|
|||
continue
|
||||
}
|
||||
|
||||
// Presentation overlay (priority, blurb, docs) is keyed by the prefix-based
|
||||
// group name; when the backend introduced this provider it may have no
|
||||
// overlay entry, so fall back to the backend/env metadata for display.
|
||||
const meta = providerMeta(name)
|
||||
|
||||
groups.push({
|
||||
|
|
|
|||
|
|
@ -108,6 +108,12 @@ export interface EnvVarInfo {
|
|||
description: string
|
||||
is_password: boolean
|
||||
is_set: boolean
|
||||
// Backend-derived provider grouping hints (from the unified provider catalog
|
||||
// in hermes_cli/provider_catalog.py). When present, the Keys tab groups by
|
||||
// this provider identity — the SAME one `hermes model` uses — instead of
|
||||
// desktop-only env-var prefix guesses. Empty for non-provider env vars.
|
||||
provider?: string
|
||||
provider_label?: string
|
||||
redacted_value: null | string
|
||||
tools: string[]
|
||||
url: null | string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue