mirror of
https://github.com/EKKOLearnAI/hermes-web-ui.git
synced 2026-05-26 05:50:18 +00:00
badb17cf8e
* feat: integrate goal command workflow * fix: keep goal done visible * fix: add goal done slash command * fix: promote queued message on run start
133 lines
3.6 KiB
TypeScript
133 lines
3.6 KiB
TypeScript
// @vitest-environment jsdom
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { createPinia, setActivePinia } from 'pinia'
|
|
|
|
const chatApi = vi.hoisted(() => ({
|
|
registerSessionHandlers: vi.fn(),
|
|
unregisterSessionHandlers: vi.fn(),
|
|
getChatRunSocket: vi.fn(() => ({ emit: vi.fn() })),
|
|
sessionCommandHandlers: [] as Array<(event: any) => void>,
|
|
peerUserMessageHandlers: [] as Array<(event: any) => void>,
|
|
}))
|
|
|
|
vi.mock('@/api/hermes/chat', () => ({
|
|
startRunViaSocket: vi.fn(),
|
|
resumeSession: vi.fn(),
|
|
registerSessionHandlers: chatApi.registerSessionHandlers,
|
|
unregisterSessionHandlers: chatApi.unregisterSessionHandlers,
|
|
getChatRunSocket: chatApi.getChatRunSocket,
|
|
respondToolApproval: vi.fn(),
|
|
respondClarify: vi.fn(),
|
|
onPeerUserMessage: vi.fn((handler: (event: any) => void) => {
|
|
chatApi.peerUserMessageHandlers.push(handler)
|
|
return vi.fn()
|
|
}),
|
|
onSessionCommand: vi.fn((handler: (event: any) => void) => {
|
|
chatApi.sessionCommandHandlers.push(handler)
|
|
return vi.fn()
|
|
}),
|
|
}))
|
|
|
|
vi.mock('@/api/client', () => ({
|
|
getActiveProfileName: () => 'default',
|
|
}))
|
|
|
|
vi.mock('@/api/hermes/sessions', () => ({
|
|
deleteSession: vi.fn(),
|
|
fetchSession: vi.fn(),
|
|
fetchSessions: vi.fn(),
|
|
setSessionModel: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('@/api/hermes/download', () => ({
|
|
getDownloadUrl: (_path: string, name: string) => `/download/${name}`,
|
|
}))
|
|
|
|
vi.mock('@/utils/completion-sound', () => ({
|
|
primeCompletionSound: vi.fn(),
|
|
playCompletionSound: vi.fn(),
|
|
}))
|
|
|
|
import { useChatStore, type Session } from '@/stores/hermes/chat'
|
|
|
|
function makeSession(): Session {
|
|
return {
|
|
id: 'session-1',
|
|
title: 'session',
|
|
messages: [],
|
|
createdAt: Date.now(),
|
|
updatedAt: Date.now(),
|
|
}
|
|
}
|
|
|
|
describe('chat store session.command fanout', () => {
|
|
beforeEach(() => {
|
|
vi.resetAllMocks()
|
|
chatApi.sessionCommandHandlers = []
|
|
chatApi.peerUserMessageHandlers = []
|
|
setActivePinia(createPinia())
|
|
})
|
|
|
|
it('attaches to a goal resume run started from another window', () => {
|
|
const store = useChatStore()
|
|
const session = makeSession()
|
|
store.sessions = [session]
|
|
store.activeSessionId = 'session-1'
|
|
store.activeSession = session
|
|
|
|
expect(chatApi.sessionCommandHandlers).toHaveLength(1)
|
|
|
|
chatApi.sessionCommandHandlers[0]({
|
|
event: 'session.command',
|
|
session_id: 'session-1',
|
|
command: 'goal',
|
|
action: 'resume',
|
|
message: 'Goal resumed',
|
|
started: true,
|
|
terminal: false,
|
|
})
|
|
|
|
expect(store.isStreaming).toBe(true)
|
|
expect(chatApi.registerSessionHandlers).toHaveBeenCalledWith('session-1', expect.objectContaining({
|
|
onRunStarted: expect.any(Function),
|
|
onSessionCommand: expect.any(Function),
|
|
}))
|
|
expect(store.messages).toEqual([
|
|
expect.objectContaining({
|
|
role: 'command',
|
|
content: 'Goal resumed',
|
|
commandAction: 'resume',
|
|
}),
|
|
])
|
|
})
|
|
|
|
it('does not clear the transcript for goal done commands', () => {
|
|
const store = useChatStore()
|
|
const session = makeSession()
|
|
session.messages = [
|
|
{ id: 'user-1', role: 'user', content: 'keep me', timestamp: 1 },
|
|
]
|
|
store.sessions = [session]
|
|
store.activeSessionId = 'session-1'
|
|
store.activeSession = session
|
|
|
|
chatApi.sessionCommandHandlers[0]({
|
|
event: 'session.command',
|
|
session_id: 'session-1',
|
|
command: 'goal',
|
|
action: 'clear',
|
|
message: 'Goal cleared.',
|
|
terminal: true,
|
|
})
|
|
|
|
expect(store.messages).toEqual([
|
|
expect.objectContaining({ id: 'user-1', content: 'keep me' }),
|
|
expect.objectContaining({
|
|
role: 'command',
|
|
content: 'Goal cleared.',
|
|
commandAction: 'clear',
|
|
}),
|
|
])
|
|
})
|
|
})
|