import { fetchEventSource } from '@microsoft/fetch-event-source'; import type { EventSourceMessage } from '@microsoft/fetch-event-source'; import { useEnterpriseStore } from '@/stores/modules/enterprise'; import { glsWithCatch } from '@/utils/stroage'; import { BASE_PYTHON_URL } from '@/api/all/chat'; import { genRandomId } from '@/utils/tools'; const DEFAULT_SSE_URL = `${BASE_PYTHON_URL}/api/agent/runs`; const SSE_HEADERS = { 'Content-Type': 'application/json', 'Cache-Control': 'no-cache', Connection: 'keep-alive', Accept: 'text/event-stream', requestid: genRandomId(), }; interface SSEConfig { headers?: Record; method?: string; body?: any; handleMessage?: (data: any) => void; handleError?: (err: any) => number | null | undefined | void; handleClose?: () => void; handleOpen?: (response: Response) => void; } /** * 创建服务器发送事件(SSE)连接 * @param config SSE 配置 * @param url 可选的自定义 URL * @returns 包含abort方法的对象,用于中断SSE连接 */ export default async (config: SSEConfig, url: string = DEFAULT_SSE_URL): Promise<{ abort: () => void }> => { const { body = undefined, headers = {}, method = 'post', handleMessage, handleError, handleOpen, handleClose, } = config; const store = useEnterpriseStore(); // 创建AbortController实例用于中断请求 const abortController = new AbortController(); fetchEventSource(url, { method, // credentials: 'include', headers: { ...SSE_HEADERS, Authorization: glsWithCatch('accessToken'), 'enterprise-id': store.enterpriseInfo?.id?.toString(), ...headers, }, body, signal: abortController.signal, // 传递signal给fetchEventSource openWhenHidden: true, // 用户切换到另一个页面后仍能保持SSE连接 onmessage(event: EventSourceMessage) { if (event.data) { try { const parsedData = JSON.parse(event.data); handleMessage?.({ ...event, data: parsedData }); } catch (error) { console.error('Error parsing SSE message:', error); handleError(new Error('Failed to parse SSE message')); } } }, onerror(error: Error) { // console.error('SSE error:', error); handleError?.(error); }, onclose() { // console.log('SSE connection closed'); handleClose?.(); }, async onopen(response: Response) { // console.log('onopen', response); handleOpen?.(response); }, }); // 返回abort方法供外部调用 return { abort: () => abortController.abort(), }; };