feat(agent): 添加流式对话API实现
实现基于SSE的流式对话接口,支持消息发送和回调处理 添加@microsoft/fetch-event-source依赖
This commit is contained in:
parent
e60dac31fd
commit
935c662203
|
|
@ -20,6 +20,7 @@
|
|||
"prepare": ""
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/fetch-event-source": "^2.0.1",
|
||||
"@unhead/vue": "2.0.19",
|
||||
"@vant/touch-emulator": "^1.4.0",
|
||||
"@vant/use": "^1.6.0",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
'@microsoft/fetch-event-source':
|
||||
specifier: ^2.0.1
|
||||
version: 2.0.1
|
||||
'@unhead/vue':
|
||||
specifier: 2.0.19
|
||||
version: 2.0.19(vue@3.5.25(typescript@5.9.3))
|
||||
|
|
@ -1017,6 +1020,9 @@ packages:
|
|||
'@jridgewell/trace-mapping@0.3.31':
|
||||
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||
|
||||
'@microsoft/fetch-event-source@2.0.1':
|
||||
resolution: {integrity: sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==}
|
||||
|
||||
'@noble/hashes@1.8.0':
|
||||
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
|
||||
engines: {node: ^14.21.3 || >=16}
|
||||
|
|
@ -5053,6 +5059,8 @@ snapshots:
|
|||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
'@microsoft/fetch-event-source@2.0.1': {}
|
||||
|
||||
'@noble/hashes@1.8.0': {}
|
||||
|
||||
'@paralleldrive/cuid2@2.3.1':
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
const AGENT_BASE_URL = '';
|
||||
|
||||
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
||||
|
||||
export const baseInfoApi = () => {
|
||||
return fetch(`${AGENT_BASE_URL}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式对话接口,返回流式 JSON 数据,形如 {"text":"我来"}
|
||||
* @param message 用户消息
|
||||
* @param callbacks 回调函数对象
|
||||
* @param options 可选配置,包含 abort signal
|
||||
* @example
|
||||
* // 使用示例:
|
||||
* streamApi('你好', {
|
||||
* onopen(response) {
|
||||
* console.log('连接已建立', response);
|
||||
* },
|
||||
* onmessage(data) {
|
||||
* // data 是服务器发送的原始字符串,如 '{"text":"我来"}'
|
||||
* console.log('收到消息:', data);
|
||||
* },
|
||||
* onclose() {
|
||||
* console.log('连接已关闭');
|
||||
* },
|
||||
* onerror(error) {
|
||||
* console.error('连接错误:', error);
|
||||
* }
|
||||
* }, { signal: abortController.signal });
|
||||
*/
|
||||
export const streamApi = (
|
||||
message: string,
|
||||
callbacks: {
|
||||
onopen?: (response: Response) => void;
|
||||
onmessage?: (data: string) => void;
|
||||
onclose?: () => void;
|
||||
onerror?: (error: Error) => void;
|
||||
},
|
||||
options?: { signal?: AbortSignal }
|
||||
) => {
|
||||
// 启动 fetchEventSource
|
||||
fetchEventSource(`${AGENT_BASE_URL}/stream`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ message }),
|
||||
signal: options?.signal,
|
||||
async onopen(response) {
|
||||
// 检查响应是否正常
|
||||
if (response.ok && response.headers.get('content-type')?.includes('text/event-stream')) {
|
||||
// 连接成功,调用 onopen 回调
|
||||
callbacks.onopen?.(response);
|
||||
} else {
|
||||
// 如果响应不正常,抛出错误
|
||||
throw new Error(`SSE 连接失败: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
},
|
||||
onmessage(msg) {
|
||||
// 处理服务器发送的消息
|
||||
// msg.data 应该是 JSON 字符串,如 {"text":"..."}
|
||||
try {
|
||||
const data = msg.data;
|
||||
console.log('Received message:', data);
|
||||
if (data && data !== '[DONE]') {
|
||||
callbacks.onmessage?.(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('处理 SSE 消息时出错:', error);
|
||||
}
|
||||
},
|
||||
onclose() {
|
||||
// 连接关闭
|
||||
console.log('SSE 连接已关闭');
|
||||
callbacks.onclose?.();
|
||||
},
|
||||
onerror(err) {
|
||||
// 发生错误
|
||||
console.error('SSE 连接错误:', err);
|
||||
callbacks.onerror?.(err instanceof Error ? err : new Error(String(err)));
|
||||
|
||||
// 重新抛出错误以停止重试
|
||||
throw err;
|
||||
},
|
||||
}).catch(error => {
|
||||
// 捕获 fetchEventSource 的 Promise 拒绝
|
||||
if (error.name !== 'AbortError') {
|
||||
console.error('fetchEventSource 错误:', error);
|
||||
callbacks.onerror?.(error instanceof Error ? error : new Error(String(error)));
|
||||
} else {
|
||||
// AbortError 是正常的取消操作,不需要调用 onerror
|
||||
console.log('请求已被取消');
|
||||
}
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue