Improve profile runtime controls (#868)
* Improve profile runtime controls * Restore profile selector test id * Update profile switch e2e flow
This commit is contained in:
@@ -98,9 +98,10 @@ test('uses the newly selected profile for the next chat-run socket after profile
|
||||
}, defaultRun.run.session_id)
|
||||
await expect(page.getByRole('button', { name: 'Stop' })).toHaveCount(0)
|
||||
|
||||
await page.locator('[data-testid="profile-selector-select"] .n-base-selection').click()
|
||||
await page.getByTestId('profile-selector-select').click()
|
||||
await expect(page.getByRole('dialog').filter({ hasText: 'research' })).toBeVisible()
|
||||
const reloadPromise = page.waitForEvent('framenavigated', frame => frame === page.mainFrame())
|
||||
await page.locator('.n-base-select-option', { hasText: /^research$/ }).click()
|
||||
await page.locator('.profile-runtime-item').filter({ hasText: /^research/ }).getByRole('button', { name: 'Switch Profile' }).click()
|
||||
await reloadPromise
|
||||
await page.waitForLoadState('domcontentloaded')
|
||||
await expect(page.getByTestId('profile-selector-select').filter({ hasText: 'research' })).toBeVisible()
|
||||
|
||||
@@ -159,6 +159,24 @@ export async function mockHermesApi(page: Page, options: MockHermesApiOptions =
|
||||
return
|
||||
}
|
||||
|
||||
if (pathname === '/api/hermes/profiles/runtime-statuses') {
|
||||
await route.fulfill(jsonResponse({
|
||||
profiles: [
|
||||
{
|
||||
profile: 'default',
|
||||
bridge: { running: activeProfileName === 'default', profile: 'default', reachable: true },
|
||||
gateway: { running: true, profile: 'default' },
|
||||
},
|
||||
{
|
||||
profile: 'research',
|
||||
bridge: { running: activeProfileName === 'research', profile: 'research', reachable: true },
|
||||
gateway: { running: true, profile: 'research' },
|
||||
},
|
||||
],
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
if (pathname === '/api/hermes/profiles/active') {
|
||||
if (request.method() !== 'PUT') {
|
||||
await route.fulfill(jsonResponse({ error: 'Method not allowed' }, 405))
|
||||
|
||||
@@ -48,6 +48,30 @@ describe('agent bridge manager command resolution', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('discovers hermes-agent from a global lib install next to the hermes command', async () => {
|
||||
const installDir = join(tempDir, 'usr', 'local')
|
||||
const binDir = join(installDir, 'bin')
|
||||
const agentRoot = join(installDir, 'lib', 'hermes-agent')
|
||||
const fakePython = join(binDir, 'python')
|
||||
const fakeHermes = join(binDir, 'hermes')
|
||||
const homeDir = join(tempDir, 'home')
|
||||
mkdirSync(binDir, { recursive: true })
|
||||
mkdirSync(agentRoot, { recursive: true })
|
||||
mkdirSync(homeDir, { recursive: true })
|
||||
writeFileSync(join(agentRoot, 'run_agent.py'), '')
|
||||
writeFileSync(fakePython, '#!/bin/sh\n')
|
||||
chmodSync(fakePython, 0o755)
|
||||
writeFileSync(fakeHermes, `#!${fakePython}\n`)
|
||||
chmodSync(fakeHermes, 0o755)
|
||||
process.env.HERMES_HOME = homeDir
|
||||
process.env.HERMES_BIN = fakeHermes
|
||||
|
||||
const { resolveAgentBridgeCommand } = await import('../../packages/server/src/services/hermes/agent-bridge/manager')
|
||||
const command = resolveAgentBridgeCommand()
|
||||
|
||||
expect(command.agentRoot).toBe(agentRoot)
|
||||
})
|
||||
|
||||
it('falls back to system Python instead of uv when no source root exists', async () => {
|
||||
const homeDir = join(tempDir, 'home')
|
||||
const fakePython = join(tempDir, 'python3')
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
gatewayStatusLooksRuntimeLocked,
|
||||
gatewayStatusLooksRunning,
|
||||
parseGatewayStatusesFromProfileListOutput,
|
||||
} from '../../packages/server/src/services/hermes/gateway-autostart'
|
||||
|
||||
describe('gateway autostart status parsing', () => {
|
||||
@@ -14,4 +15,24 @@ describe('gateway autostart status parsing', () => {
|
||||
it('does not treat not-running status as running', () => {
|
||||
expect(gatewayStatusLooksRunning('Gateway is not running')).toBe(false)
|
||||
})
|
||||
|
||||
it('parses gateway status from hermes profile list output', () => {
|
||||
const output = `
|
||||
Profile Model Gateway Alias Distribution
|
||||
─────────────── ─────────────────────────── ─────────── ─────────── ────────────────────
|
||||
◆default glm-5-turbo running — —
|
||||
akri glm-5-turbo running akri —
|
||||
tester gpt-5.5 stopped tester —
|
||||
`
|
||||
const statuses = parseGatewayStatusesFromProfileListOutput(output)
|
||||
expect(statuses.get('default')).toBe('running')
|
||||
expect(statuses.get('akri')).toBe('running')
|
||||
expect(statuses.get('tester')).toBe('stopped')
|
||||
})
|
||||
|
||||
it('uses profile-list gateway status text for running checks', () => {
|
||||
expect(gatewayStatusLooksRunning('running')).toBe(true)
|
||||
expect(gatewayStatusLooksRunning('stopped')).toBe(false)
|
||||
expect(gatewayStatusLooksRunning('not running')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user