fix session profile listing and cli sqlite warning (#971)
This commit is contained in:
@@ -79,12 +79,22 @@ describe('API Client', () => {
|
||||
localStorage.setItem('hermes_active_profile_name', 'default')
|
||||
mockFetch.mockResolvedValue({ ok: true, status: 200, json: () => ({ data: 1 }) })
|
||||
|
||||
await request('/api/hermes/sessions')
|
||||
await request('/api/hermes/sessions/session-1')
|
||||
|
||||
const [, options] = mockFetch.mock.calls[0]
|
||||
expect(options.headers['X-Hermes-Profile']).toBe('default')
|
||||
})
|
||||
|
||||
it('does not add the active profile header to profile-wide session collection requests', async () => {
|
||||
localStorage.setItem('hermes_active_profile_name', 'research')
|
||||
mockFetch.mockResolvedValue({ ok: true, status: 200, json: () => ({ data: 1 }) })
|
||||
|
||||
await request('/api/hermes/sessions')
|
||||
|
||||
const [, options] = mockFetch.mock.calls[0]
|
||||
expect(options.headers['X-Hermes-Profile']).toBeUndefined()
|
||||
})
|
||||
|
||||
it('does not add Authorization header when no token', async () => {
|
||||
mockFetch.mockResolvedValue({ ok: true, status: 200, json: () => ({ data: 1 }) })
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ describe('CLI port detection', () => {
|
||||
|
||||
try {
|
||||
const { resetDefaultLogin } = await loadCli()
|
||||
const created = resetDefaultLogin({ silent: true })
|
||||
const created = await resetDefaultLogin({ silent: true })
|
||||
expect(created.action).toBe('created')
|
||||
|
||||
const db = new DatabaseSync(dbPath)
|
||||
@@ -144,7 +144,7 @@ describe('CLI port detection', () => {
|
||||
db.close()
|
||||
}
|
||||
|
||||
const updated = resetDefaultLogin({ silent: true })
|
||||
const updated = await resetDefaultLogin({ silent: true })
|
||||
expect(updated.action).toBe('updated')
|
||||
|
||||
const verifyDb = new DatabaseSync(dbPath)
|
||||
|
||||
@@ -22,6 +22,7 @@ const getLocalUsageStatsMock = vi.fn()
|
||||
const getActiveProfileNameMock = vi.fn()
|
||||
const loggerWarnMock = vi.fn()
|
||||
const getCompressionSnapshotMock = vi.fn()
|
||||
const listUserProfilesMock = vi.fn()
|
||||
|
||||
vi.mock('../../packages/server/src/db/hermes/conversations-db', () => ({
|
||||
listConversationSummariesFromDb: listConversationSummariesFromDbMock,
|
||||
@@ -68,6 +69,10 @@ vi.mock('../../packages/server/src/db/hermes/session-store', () => ({
|
||||
updateSession: localUpdateSessionMock,
|
||||
}))
|
||||
|
||||
vi.mock('../../packages/server/src/db/hermes/users-store', () => ({
|
||||
listUserProfiles: listUserProfilesMock,
|
||||
}))
|
||||
|
||||
vi.mock('../../packages/server/src/db/hermes/usage-store', () => ({
|
||||
deleteUsage: vi.fn(),
|
||||
getUsage: vi.fn(),
|
||||
@@ -130,6 +135,8 @@ describe('session conversations controller', () => {
|
||||
getActiveProfileNameMock.mockReturnValue('default')
|
||||
loggerWarnMock.mockReset()
|
||||
getCompressionSnapshotMock.mockReset()
|
||||
listUserProfilesMock.mockReset()
|
||||
listUserProfilesMock.mockReturnValue([])
|
||||
})
|
||||
|
||||
it('lists conversations from the local session store', async () => {
|
||||
@@ -165,6 +172,120 @@ describe('session conversations controller', () => {
|
||||
expect(ctx.body.sessions[0]).toMatchObject({ id: 'local-conversation', source: 'cli', title: 'Local' })
|
||||
})
|
||||
|
||||
it('lists all account-accessible single-chat sessions when only the active profile header is present', async () => {
|
||||
listUserProfilesMock.mockReturnValue([{ profile_name: 'default' }, { profile_name: 'travel' }])
|
||||
localListSessionsMock.mockReturnValue([
|
||||
{
|
||||
id: 'default-session',
|
||||
profile: 'default',
|
||||
source: 'cli',
|
||||
model: 'gpt-5',
|
||||
title: 'Default',
|
||||
started_at: 1,
|
||||
ended_at: null,
|
||||
last_active: 3,
|
||||
message_count: 1,
|
||||
tool_call_count: 0,
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
cache_read_tokens: 0,
|
||||
cache_write_tokens: 0,
|
||||
reasoning_tokens: 0,
|
||||
billing_provider: null,
|
||||
estimated_cost_usd: 0,
|
||||
actual_cost_usd: null,
|
||||
cost_status: '',
|
||||
preview: '',
|
||||
},
|
||||
{
|
||||
id: 'travel-session',
|
||||
profile: 'travel',
|
||||
source: 'cli',
|
||||
model: 'gpt-5',
|
||||
title: 'Travel',
|
||||
started_at: 2,
|
||||
ended_at: null,
|
||||
last_active: 4,
|
||||
message_count: 1,
|
||||
tool_call_count: 0,
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
cache_read_tokens: 0,
|
||||
cache_write_tokens: 0,
|
||||
reasoning_tokens: 0,
|
||||
billing_provider: null,
|
||||
estimated_cost_usd: 0,
|
||||
actual_cost_usd: null,
|
||||
cost_status: '',
|
||||
preview: '',
|
||||
},
|
||||
{
|
||||
id: 'secret-session',
|
||||
profile: 'secret',
|
||||
source: 'cli',
|
||||
model: 'gpt-5',
|
||||
title: 'Secret',
|
||||
started_at: 3,
|
||||
ended_at: null,
|
||||
last_active: 5,
|
||||
message_count: 1,
|
||||
tool_call_count: 0,
|
||||
input_tokens: 0,
|
||||
output_tokens: 0,
|
||||
cache_read_tokens: 0,
|
||||
cache_write_tokens: 0,
|
||||
reasoning_tokens: 0,
|
||||
billing_provider: null,
|
||||
estimated_cost_usd: 0,
|
||||
actual_cost_usd: null,
|
||||
cost_status: '',
|
||||
preview: '',
|
||||
},
|
||||
])
|
||||
|
||||
const mod = await import('../../packages/server/src/controllers/hermes/sessions')
|
||||
const ctx: any = {
|
||||
query: {},
|
||||
state: {
|
||||
user: { id: 1, role: 'admin' },
|
||||
profile: { name: 'travel' },
|
||||
},
|
||||
body: null,
|
||||
}
|
||||
await mod.list(ctx)
|
||||
|
||||
expect(localListSessionsMock).toHaveBeenCalledWith(undefined, undefined, 2000)
|
||||
expect(ctx.body.sessions.map((session: any) => session.id)).toEqual(['default-session', 'travel-session'])
|
||||
})
|
||||
|
||||
it('filters the single-chat session list when profile is explicitly provided', async () => {
|
||||
localListSessionsMock.mockReturnValue([])
|
||||
|
||||
const mod = await import('../../packages/server/src/controllers/hermes/sessions')
|
||||
const ctx: any = {
|
||||
query: { profile: 'travel' },
|
||||
state: { profile: { name: 'default' } },
|
||||
body: null,
|
||||
}
|
||||
await mod.list(ctx)
|
||||
|
||||
expect(localListSessionsMock).toHaveBeenCalledWith('travel', undefined, 2000)
|
||||
})
|
||||
|
||||
it('searches all account-accessible single-chat sessions unless profile is explicit', async () => {
|
||||
localSearchSessionsMock.mockReturnValue([])
|
||||
|
||||
const mod = await import('../../packages/server/src/controllers/hermes/sessions')
|
||||
const ctx: any = {
|
||||
query: { q: 'docker', limit: '10' },
|
||||
state: { profile: { name: 'travel' } },
|
||||
body: null,
|
||||
}
|
||||
await mod.search(ctx)
|
||||
|
||||
expect(localSearchSessionsMock).toHaveBeenCalledWith(undefined, 'docker', 10)
|
||||
})
|
||||
|
||||
it('propagates local session store errors for conversation summaries', async () => {
|
||||
localListSessionsMock.mockImplementation(() => {
|
||||
throw new Error('db unavailable')
|
||||
|
||||
Reference in New Issue
Block a user