mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(desktop): scope session list to active profile + longer timeout
The desktop sidebar fetched the unified cross-profile session list as profile='all' and filtered it client-side by the active profile. On a large multi-profile install the active profile's rows could be windowed out of the cross-profile recency page entirely, so switching to a profile agent showed an empty history panel (and the 'all' fetch could exceed the 15s IPC timeout on startup). Scope the fetch to the active profile so its own page comes back on its merits, and bump the session-list IPC timeout to 60s. profileScope is now a refreshSessions dep, so the existing gateway-open effect re-pulls on profile switch.
This commit is contained in:
parent
330ca4585b
commit
b55ac45264
3 changed files with 69 additions and 5 deletions
|
|
@ -29,7 +29,14 @@ import {
|
|||
unpinSession
|
||||
} from '../store/layout'
|
||||
import { $filePreviewTarget, $previewTarget, closeActiveRightRailTab } from '../store/preview'
|
||||
import { $activeGatewayProfile, $freshSessionRequest, normalizeProfileKey, refreshActiveProfile } from '../store/profile'
|
||||
import {
|
||||
$activeGatewayProfile,
|
||||
$freshSessionRequest,
|
||||
$profileScope,
|
||||
ALL_PROFILES,
|
||||
normalizeProfileKey,
|
||||
refreshActiveProfile
|
||||
} from '../store/profile'
|
||||
import {
|
||||
$activeSessionId,
|
||||
$currentCwd,
|
||||
|
|
@ -157,6 +164,7 @@ export function DesktopController() {
|
|||
const selectedStoredSessionId = useStore($selectedStoredSessionId)
|
||||
const terminalTakeover = useStore($terminalTakeover)
|
||||
const panesFlipped = useStore($panesFlipped)
|
||||
const profileScope = useStore($profileScope)
|
||||
|
||||
const routedSessionId = routeSessionId(location.pathname)
|
||||
const routeToken = `${location.pathname}:${location.search}:${location.hash}`
|
||||
|
|
@ -288,7 +296,11 @@ export function DesktopController() {
|
|||
// the same rows tagged profile="default". Cron sessions are excluded here
|
||||
// and fetched separately (refreshCronSessions) so the scheduler's
|
||||
// always-newest rows can't consume the recents page budget.
|
||||
const result = await listAllProfileSessions(limit, 1, 'exclude', 'recent', 'all', {
|
||||
// Scope the fetch to the active profile (not always 'all') so a profile
|
||||
// with few recent sessions isn't windowed out of the cross-profile
|
||||
// recency page — the empty-history-on-profile-switch bug.
|
||||
const sessionProfile = profileScope === ALL_PROFILES ? 'all' : profileScope
|
||||
const result = await listAllProfileSessions(limit, 1, 'exclude', 'recent', sessionProfile, {
|
||||
excludeSources: ['cron']
|
||||
})
|
||||
|
||||
|
|
@ -305,7 +317,7 @@ export function DesktopController() {
|
|||
|
||||
void refreshCronSessions()
|
||||
void refreshCronJobs()
|
||||
}, [refreshCronSessions, refreshCronJobs])
|
||||
}, [profileScope, refreshCronSessions, refreshCronJobs])
|
||||
|
||||
const loadMoreSessions = useCallback(() => {
|
||||
bumpSessionsLimit()
|
||||
|
|
|
|||
49
apps/desktop/src/hermes.test.ts
Normal file
49
apps/desktop/src/hermes.test.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { listAllProfileSessions, listSessions } from './hermes'
|
||||
|
||||
const emptySessionsResponse = {
|
||||
limit: 0,
|
||||
offset: 0,
|
||||
sessions: [],
|
||||
total: 0
|
||||
}
|
||||
|
||||
describe('Hermes REST session helpers', () => {
|
||||
let api: ReturnType<typeof vi.fn>
|
||||
|
||||
beforeEach(() => {
|
||||
api = vi.fn().mockResolvedValue(emptySessionsResponse)
|
||||
Object.defineProperty(window, 'hermesDesktop', {
|
||||
configurable: true,
|
||||
value: { api }
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks()
|
||||
Reflect.deleteProperty(window, 'hermesDesktop')
|
||||
})
|
||||
|
||||
it('uses a longer timeout for the single-profile session list', async () => {
|
||||
await listSessions(50, 1)
|
||||
|
||||
expect(api).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
path: '/api/sessions?limit=50&offset=0&min_messages=1&archived=exclude&order=recent',
|
||||
timeoutMs: 60_000
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it('uses a longer timeout for the all-profile session list', async () => {
|
||||
await listAllProfileSessions(50, 1)
|
||||
|
||||
expect(api).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
path: '/api/profiles/sessions?limit=50&offset=0&min_messages=1&archived=exclude&order=recent&profile=all',
|
||||
timeoutMs: 60_000
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
@ -42,6 +42,7 @@ import type {
|
|||
} from '@/types/hermes'
|
||||
|
||||
const DEFAULT_GATEWAY_REQUEST_TIMEOUT_MS = 30_000
|
||||
const SESSION_LIST_REQUEST_TIMEOUT_MS = 60_000
|
||||
|
||||
export type {
|
||||
ActionResponse,
|
||||
|
|
@ -136,7 +137,8 @@ export async function listSessions(
|
|||
order: 'created' | 'recent' = 'recent'
|
||||
): Promise<PaginatedSessions> {
|
||||
const result = await window.hermesDesktop.api<PaginatedSessions>({
|
||||
path: `/api/sessions?limit=${limit}&offset=0&min_messages=${Math.max(0, minMessages)}&archived=${archived}&order=${order}`
|
||||
path: `/api/sessions?limit=${limit}&offset=0&min_messages=${Math.max(0, minMessages)}&archived=${archived}&order=${order}`,
|
||||
timeoutMs: SESSION_LIST_REQUEST_TIMEOUT_MS
|
||||
})
|
||||
|
||||
return {
|
||||
|
|
@ -176,7 +178,8 @@ export async function listAllProfileSessions(
|
|||
const result = await window.hermesDesktop.api<PaginatedSessions>({
|
||||
path:
|
||||
`/api/profiles/sessions?limit=${limit}&offset=0&min_messages=${Math.max(0, minMessages)}` +
|
||||
`&archived=${archived}&order=${order}&profile=${encodeURIComponent(profile)}${sourceParam}${excludeParam}`
|
||||
`&archived=${archived}&order=${order}&profile=${encodeURIComponent(profile)}${sourceParam}${excludeParam}`,
|
||||
timeoutMs: SESSION_LIST_REQUEST_TIMEOUT_MS
|
||||
})
|
||||
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue