fix: harden Hermes stream recovery around tool boundaries (#189)
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
// @vitest-environment jsdom
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { streamRunEvents, type RunEvent } from '@/api/hermes/chat'
|
||||
|
||||
class MockEventSource {
|
||||
static instances: MockEventSource[] = []
|
||||
|
||||
url: string
|
||||
onmessage: ((event: { data: string }) => void) | null = null
|
||||
onerror: (() => void) | null = null
|
||||
close = vi.fn()
|
||||
|
||||
constructor(url: string) {
|
||||
this.url = url
|
||||
MockEventSource.instances.push(this)
|
||||
}
|
||||
|
||||
emit(data: string) {
|
||||
this.onmessage?.({ data })
|
||||
}
|
||||
|
||||
fail() {
|
||||
this.onerror?.()
|
||||
}
|
||||
}
|
||||
|
||||
describe('streamRunEvents', () => {
|
||||
beforeEach(() => {
|
||||
window.localStorage.clear()
|
||||
MockEventSource.instances = []
|
||||
vi.stubGlobal('EventSource', MockEventSource)
|
||||
})
|
||||
|
||||
it('maps non-JSON EventSource data to message.delta so raw text is rendered', () => {
|
||||
const events: RunEvent[] = []
|
||||
|
||||
streamRunEvents('run-raw', event => events.push(event), vi.fn(), vi.fn())
|
||||
MockEventSource.instances[0].emit('原因:raw fallback')
|
||||
|
||||
expect(events).toEqual([{ event: 'message.delta', delta: '原因:raw fallback' }])
|
||||
})
|
||||
|
||||
it('parses colon-containing JSON deltas and closes on completion', () => {
|
||||
const events: RunEvent[] = []
|
||||
const onDone = vi.fn()
|
||||
|
||||
streamRunEvents('run-json', event => events.push(event), onDone, vi.fn())
|
||||
const source = MockEventSource.instances[0]
|
||||
source.emit(JSON.stringify({ event: 'message.delta', delta: '让我直接读文件:A: B' }))
|
||||
source.emit(JSON.stringify({ event: 'run.completed' }))
|
||||
|
||||
expect(events).toEqual([
|
||||
{ event: 'message.delta', delta: '让我直接读文件:A: B' },
|
||||
{ event: 'run.completed' },
|
||||
])
|
||||
expect(source.close).toHaveBeenCalledTimes(1)
|
||||
expect(onDone).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user