Merge pull request #52205 from NousResearch/bb/desktop-restart-profile

fix(desktop): route gateway restart / status / update to the active profile
This commit is contained in:
brooklyn! 2026-06-24 19:28:53 -05:00 committed by GitHub
commit 42e14d1089
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 54 additions and 0 deletions

View file

@ -0,0 +1,49 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import {
checkHermesUpdate,
getActionStatus,
getStatus,
restartGateway,
setApiRequestProfile,
updateHermes
} from './hermes'
// Contract: every backend-targeted action helper must carry the active gateway
// profile, so a multi-profile / global-remote user's restart, status poll, and
// update hit the backend they're actually on — not the primary/default. The
// System-panel "restart does nothing" bug was these helpers dropping it.
describe('backend action helpers are profile-scoped', () => {
const api = vi.fn(async (_req: { path: string; profile?: string }) => ({}) as never)
beforeEach(() => {
;(window as { hermesDesktop?: unknown }).hermesDesktop = { api }
api.mockClear()
})
afterEach(() => {
setApiRequestProfile(null)
delete (window as { hermesDesktop?: unknown }).hermesDesktop
})
const lastProfile = () => api.mock.calls.at(-1)?.[0].profile
it('omits profile when none is active (single-profile users unaffected)', () => {
void getStatus()
expect(lastProfile()).toBeUndefined()
})
it('forwards the active profile to every backend action', () => {
setApiRequestProfile('coder')
void getStatus()
void restartGateway()
void updateHermes()
void checkHermesUpdate()
void getActionStatus('gateway-restart')
for (const call of api.mock.calls) {
expect(call[0].profile).toBe('coder')
}
})
})

View file

@ -274,6 +274,7 @@ export function getGlobalModelInfo(): Promise<ModelInfoResponse> {
export function getStatus(): Promise<StatusResponse> {
return window.hermesDesktop.api<StatusResponse>({
...profileScoped(),
path: '/api/status'
})
}
@ -756,6 +757,7 @@ export function setModelAssignment(body: ModelAssignmentRequest): Promise<ModelA
export function restartGateway(): Promise<ActionResponse> {
return window.hermesDesktop.api<ActionResponse>({
...profileScoped(),
path: '/api/gateway/restart',
method: 'POST'
})
@ -763,6 +765,7 @@ export function restartGateway(): Promise<ActionResponse> {
export function updateHermes(): Promise<ActionResponse> {
return window.hermesDesktop.api<ActionResponse>({
...profileScoped(),
path: '/api/hermes/update',
method: 'POST'
})
@ -773,12 +776,14 @@ export function updateHermes(): Promise<ActionResponse> {
* distinct from the Electron client clone's git state. */
export function checkHermesUpdate(force = false): Promise<BackendUpdateCheckResponse> {
return window.hermesDesktop.api<BackendUpdateCheckResponse>({
...profileScoped(),
path: `/api/hermes/update/check${force ? '?force=true' : ''}`
})
}
export function getActionStatus(name: string, lines = 200): Promise<ActionStatusResponse> {
return window.hermesDesktop.api<ActionStatusResponse>({
...profileScoped(),
path: `/api/actions/${encodeURIComponent(name)}/status?lines=${Math.max(1, lines)}`
})
}