hermes-agent/apps/desktop/src/lib/model-options.test.ts
helix4u a9b5598909 fix(desktop): load remote model options before session
Both Desktop picker surfaces (status-bar model menu, settings/onboarding
dialog) only asked the connected gateway's model.options once a session
existed; before that they fell back to the Desktop REST/global options, which
can't see virtual providers a remote gateway exposes — including the MoA
presets from #53817. Centralize the fetch rule in requestModelOptions(): prefer
the connected gateway whenever one exists (no session_id needed — the RPC
resolves disk config), REST only when no gateway is connected.

The status-bar MoA preset section now renders from the same model.options
payload (the virtual `moa` provider row) instead of the local /api/model/moa
REST config, so remote presets appear correctly; the row is filtered out of
the main provider groups so presets don't list twice. Preset selection keeps
the persistent switchTo path from #56417 and drops the vestigial session gate —
like regular model rows, a pre-session pick ships on the next session.create.

Fixes #53817.

Rebased and reconciled with #56417 (persistent MoA selection), which landed
after this PR was opened and covered its one-shot-/moa half.
2026-07-02 12:50:46 -05:00

49 lines
1.5 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest'
import { getGlobalModelOptions } from '@/hermes'
import { requestModelOptions } from './model-options'
const globalOptions = { model: 'hermes-4', provider: 'nous', providers: [] }
vi.mock('@/hermes', () => ({
getGlobalModelOptions: vi.fn(() => Promise.resolve(globalOptions))
}))
describe('requestModelOptions', () => {
afterEach(() => {
vi.clearAllMocks()
})
it('uses the connected gateway even before a session exists', async () => {
const gatewayPayload = { model: 'BeastMode', provider: 'moa', providers: [] }
const gateway = {
request: vi.fn(() => Promise.resolve(gatewayPayload))
}
await expect(requestModelOptions({ gateway: gateway as never, sessionId: null })).resolves.toBe(gatewayPayload)
expect(gateway.request).toHaveBeenCalledWith('model.options', {})
expect(getGlobalModelOptions).not.toHaveBeenCalled()
})
it('passes the active session id and refresh flag through the gateway', async () => {
const gateway = {
request: vi.fn(() => Promise.resolve(globalOptions))
}
await requestModelOptions({ gateway: gateway as never, refresh: true, sessionId: 'session-1' })
expect(gateway.request).toHaveBeenCalledWith('model.options', {
refresh: true,
session_id: 'session-1'
})
})
it('falls back to REST when no gateway is connected', async () => {
await requestModelOptions({ refresh: true })
expect(getGlobalModelOptions).toHaveBeenCalledWith({ refresh: true })
})
})