feat(chat): Implement comprehensive chat functionality for customer and advisor interactions

- Introduced new chat components including `ChatPanel` and `VisitorChatWidget` to facilitate real-time conversations for customers and visitors.
- Developed a robust chat API with endpoints for synchronous and streaming interactions, enhancing user engagement.
- Added new pages for customer interactions, including `CustomerChatPage`, `CustomerProfilePage`, `CustomerHoldingsPage`, and `CustomerTradesPage`, integrating chat capabilities seamlessly.
- Enhanced the advisor experience with the `AdvisorCustomersPage` and `RiskAlertsPage`, allowing for efficient management of customer interactions and risk alerts.
- Updated routing and state management to support new chat functionalities, ensuring a cohesive user experience across the application.

This update significantly improves the chat capabilities within the application, providing users with enhanced tools for communication and support.
This commit is contained in:
2026-09-09 20:17:50 +08:00
parent 2945108f66
commit 95969678e2
22 changed files with 1558 additions and 24 deletions
@@ -0,0 +1,48 @@
import { describe, expect, it } from 'vitest'
import { parseChatStreamBuffer, parseSseDataPayload } from '../parseChatStream'
describe('parseSseDataPayload', () => {
it('parses meta frame', () => {
const event = parseSseDataPayload(
JSON.stringify({
choices: [{ delta: { role: 'assistant' } }],
meta: { session_id: 'sess-1', has_disclaimer: true, disclaimer: '风险提示' },
}),
)
expect(event).toEqual({
type: 'meta',
meta: { session_id: 'sess-1', has_disclaimer: true, disclaimer: '风险提示' },
})
})
it('parses delta content', () => {
const event = parseSseDataPayload(
JSON.stringify({ choices: [{ delta: { content: '你好' } }] }),
)
expect(event).toEqual({ type: 'delta', content: '你好' })
})
it('parses error frame', () => {
const event = parseSseDataPayload(
JSON.stringify({ error: { code: 'STREAM_FAILED', message: '生成失败' } }),
)
expect(event).toEqual({ type: 'error', code: 'STREAM_FAILED', message: '生成失败' })
})
it('parses DONE marker', () => {
expect(parseSseDataPayload('[DONE]')).toEqual({ type: 'done' })
})
})
describe('parseChatStreamBuffer', () => {
it('walks multi-line SSE chunk', () => {
const buffer = [
'data: {"choices":[{"delta":{"content":"A"}}]}',
'',
'data: [DONE]',
'',
].join('\n')
const events = [...parseChatStreamBuffer(buffer)]
expect(events).toEqual([{ type: 'delta', content: 'A' }, { type: 'done' }])
})
})