| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- const baseURL =
- import.meta.env.VITE_API_BASE_URL || "http://localhost:8000";
- export interface ResearchRequest {
- topic: string;
- search_api?: string;
- }
- export interface ResearchStreamEvent {
- type: string;
- [key: string]: unknown;
- }
- export interface StreamOptions {
- signal?: AbortSignal;
- }
- export async function runResearchStream(
- payload: ResearchRequest,
- onEvent: (event: ResearchStreamEvent) => void,
- options: StreamOptions = {}
- ): Promise<void> {
- const response = await fetch(`${baseURL}/research/stream`, {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Accept: "text/event-stream"
- },
- body: JSON.stringify(payload),
- signal: options.signal
- });
- if (!response.ok) {
- const errorText = await response.text().catch(() => "");
- throw new Error(
- errorText || `研究请求失败,状态码:${response.status}`
- );
- }
- const body = response.body;
- if (!body) {
- throw new Error("浏览器不支持流式响应,无法获取研究进度");
- }
- const reader = body.getReader();
- const decoder = new TextDecoder("utf-8");
- let buffer = "";
- while (true) {
- const { value, done } = await reader.read();
- buffer += decoder.decode(value || new Uint8Array(), { stream: !done });
- let boundary = buffer.indexOf("\n\n");
- while (boundary !== -1) {
- const rawEvent = buffer.slice(0, boundary).trim();
- buffer = buffer.slice(boundary + 2);
- if (rawEvent.startsWith("data:")) {
- const dataPayload = rawEvent.slice(5).trim();
- if (dataPayload) {
- try {
- const event = JSON.parse(dataPayload) as ResearchStreamEvent;
- onEvent(event);
- if (event.type === "error" || event.type === "done") {
- return;
- }
- } catch (error) {
- console.error("解析流式事件失败:", error, dataPayload);
- }
- }
- }
- boundary = buffer.indexOf("\n\n");
- }
- if (done) {
- // 处理可能的尾巴事件
- if (buffer.trim()) {
- const rawEvent = buffer.trim();
- if (rawEvent.startsWith("data:")) {
- const dataPayload = rawEvent.slice(5).trim();
- if (dataPayload) {
- try {
- const event = JSON.parse(dataPayload) as ResearchStreamEvent;
- onEvent(event);
- } catch (error) {
- console.error("解析流式事件失败:", error, dataPayload);
- }
- }
- }
- }
- break;
- }
- }
- }
|