fix(frontend): refine streamed presentation and resolve stream edge cases
This commit is contained in:
parent
a3af8f45cc
commit
2cc33a721c
18 changed files with 450 additions and 46 deletions
|
|
@ -13,14 +13,16 @@ vi.mock('../src/lib/recommendationStream', async (importOriginal) => {
|
|||
const streamMock = vi.mocked(streamRecommendations)
|
||||
const unmountCallbacks: Array<() => void> = []
|
||||
|
||||
function mountChat() {
|
||||
function mountChat(
|
||||
createPlaylist: Parameters<typeof useChatStream>[0] = vi.fn(async () => ({ url: null })),
|
||||
) {
|
||||
let chat: ReturnType<typeof useChatStream> | undefined
|
||||
const root = document.createElement('div')
|
||||
document.body.append(root)
|
||||
const app = createApp(
|
||||
defineComponent({
|
||||
setup() {
|
||||
chat = useChatStream(vi.fn(async () => ({ url: null })))
|
||||
chat = useChatStream(createPlaylist)
|
||||
return () => h('div')
|
||||
},
|
||||
}),
|
||||
|
|
@ -106,6 +108,22 @@ describe('useChatStream', () => {
|
|||
expect(turn?.transportFailure).toBeNull()
|
||||
})
|
||||
|
||||
it('stores a metadata-free terminal error as a normal stream error', async () => {
|
||||
streamMock.mockImplementation(async (_request, _signal, onEvent) => {
|
||||
onEvent({ type: 'error', code: 'first_stage_failed', message: 'Planning failed.' })
|
||||
})
|
||||
const chat = mountChat()
|
||||
|
||||
await chat.send('error')
|
||||
|
||||
expect(assistantTurns(chat)[0]).toMatchObject({
|
||||
status: 'error',
|
||||
requestId: null,
|
||||
error: { code: 'first_stage_failed', message: 'Planning failed.' },
|
||||
transportFailure: null,
|
||||
})
|
||||
})
|
||||
|
||||
it('stores an incomplete stream as a transport failure', async () => {
|
||||
streamMock.mockRejectedValue(
|
||||
new StreamTransportError('unexpected_eof', 'The stream ended early.'),
|
||||
|
|
@ -239,4 +257,26 @@ describe('useChatStream', () => {
|
|||
|
||||
expect(receivedQuery).toHaveLength(1000)
|
||||
})
|
||||
|
||||
it('uses the bare query as the capped playlist name', async () => {
|
||||
const createPlaylist = vi.fn(async () => ({ url: null }))
|
||||
streamMock.mockImplementation(async (_request, _signal, onEvent) => {
|
||||
onEvent(metadata('playlist'))
|
||||
onEvent(track(1))
|
||||
onEvent({ type: 'done', track_count: 1, total_ms: 5 })
|
||||
})
|
||||
const chat = mountChat(createPlaylist)
|
||||
const query = `Late-night instrumental focus ${'x'.repeat(100)}`
|
||||
|
||||
await chat.send(query)
|
||||
const turn = assistantTurns(chat)[0]
|
||||
if (!turn) throw new Error('Assistant turn was not created.')
|
||||
await chat.savePlaylist(turn.id)
|
||||
|
||||
expect(createPlaylist).toHaveBeenCalledWith({
|
||||
schema_version: 1,
|
||||
name: query.slice(0, 100),
|
||||
track_uris: ['spotify:track:1'],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue