fix: restore dataflow defaults and SSE response (#16290)

This commit is contained in:
buua436
2026-06-24 11:51:24 +08:00
committed by GitHub
parent 398f488b1b
commit 8d4f4a093b
2 changed files with 73 additions and 73 deletions

View File

@@ -123,6 +123,11 @@ export const useSendMessageBySSE = (url: string) => {
body: JSON.stringify(body),
signal: controller?.signal || sseRef.current?.signal,
});
const responseDataPromise = response
.clone()
.json()
.then((data: ResponseType) => data)
.catch(() => undefined);
if (!response.ok) {
let errorMessage = response.statusText || 'Request failed';
try {
@@ -135,8 +140,6 @@ export const useSendMessageBySSE = (url: string) => {
} catch {
// Non-JSON error body; fall back to the HTTP status text.
}
setDone(true);
resetAnswerList();
return {
response,
data: {
@@ -152,76 +155,81 @@ export const useSendMessageBySSE = (url: string) => {
?.pipeThrough(new TextDecoderStream())
.pipeThrough(new EventSourceParserStream())
.getReader();
let lastEventData: ResponseType | undefined;
// eslint-disable-next-line no-constant-condition
while (true) {
try {
try {
// eslint-disable-next-line no-constant-condition
while (true) {
const x = await reader?.read();
if (x) {
const { done, value } = x;
if (done) {
console.info('done');
resetAnswerList();
break;
}
try {
const raw = (value?.data ?? '').trim();
// SSE end-of-stream sentinel — no payload, skip without
// surfacing a JSON.parse error to the console.
if (!raw) {
continue;
}
// Some upstreams double-wrap the body in a `data:` prefix;
// strip one layer so JSON.parse sees a real object.
const payload = raw.startsWith('data:')
? raw.slice(5).trimStart()
: raw;
// Check the sentinel after prefix stripping so a
// `data: [DONE]` payload is caught and the stream
// loop is terminated.
if (payload === '[DONE]') {
break;
}
const val = JSON.parse(payload);
console.info('data:', val);
if (typeof val?.code === 'number' && val.code !== 0) {
message.error(val.message);
}
setAnswerList((list) => {
const nextList = [...list];
nextList.push(val);
return nextList;
});
} catch (e) {
console.warn(e);
}
}
} catch (e) {
if (e instanceof DOMException && e.name === 'AbortError') {
console.log('Request was aborted by user or logic.');
if (!x) {
break;
}
const { done, value } = x;
if (done) {
break;
}
try {
const raw = (value?.data ?? '').trim();
// SSE end-of-stream sentinel — no payload, skip without
// surfacing a JSON.parse error to the console.
if (!raw) {
continue;
}
// Some upstreams double-wrap the body in a `data:` prefix;
// strip one layer so JSON.parse sees a real object.
const payload = raw.startsWith('data:')
? raw.slice(5).trimStart()
: raw;
// Check the sentinel after prefix stripping so a
// `data: [DONE]` payload is caught and the stream
// loop is terminated.
if (payload === '[DONE]') {
break;
}
const val = JSON.parse(payload);
if (typeof val?.code === 'number' && val.code !== 0) {
message.error(val.message);
}
lastEventData = val as ResponseType;
setAnswerList((list) => {
const nextList = [...list];
nextList.push(val);
return nextList;
});
} catch (e) {
console.warn(e);
}
}
} catch (e) {
if (e instanceof DOMException && e.name === 'AbortError') {
console.log('Request was aborted by user or logic.');
} else {
throw e;
}
}
console.info('done?');
setDone(true);
resetAnswerList();
const responseData = await responseDataPromise;
return {
response,
data: {
code: 0,
data: true,
message: 'success',
status: response.status,
},
data:
responseData ??
lastEventData ??
({
code: 0,
data: true,
message: 'success',
status: response.status,
} as ResponseType),
};
} catch (e) {
console.warn(e);
return undefined;
} finally {
setDone(true);
resetAnswerList();
console.warn(e);
}
},
[initializeSseRef, url, resetAnswerList],

View File

@@ -1,14 +1,6 @@
const FILE_ID = 'File';
import { FileId, initialParserValues } from '@/pages/agent/constant/pipeline';
const FILE_OPERATOR = 'File';
const INITIAL_PARSER_VALUES = {
outputs: {
markdown: { type: 'string', value: '' },
text: { type: 'string', value: '' },
html: { type: 'string', value: '' },
json: { type: 'Array<object>', value: [] },
},
setups: [],
};
// Dataflow seed DSL. Kept separate from UI hooks so pure DSL helpers
// can import it without pulling React modules into tests/runtime.
@@ -16,7 +8,7 @@ export const DataflowEmptyDsl = {
graph: {
nodes: [
{
id: FILE_ID,
id: FileId,
type: 'beginNode',
position: {
x: 50,
@@ -31,7 +23,7 @@ export const DataflowEmptyDsl = {
},
{
data: {
form: INITIAL_PARSER_VALUES,
form: initialParserValues,
label: 'Parser',
name: 'Parser_0',
},
@@ -54,7 +46,7 @@ export const DataflowEmptyDsl = {
edges: [
{
id: 'xy-edge__Filestart-Parser:HipSignsRhymeend',
source: FILE_ID,
source: FileId,
sourceHandle: 'start',
target: 'Parser:HipSignsRhyme',
targetHandle: 'end',