fix(teacher): 隔离子智能体流式消息与老师正文
This commit is contained in:
@@ -257,10 +257,13 @@ it('reconnects from the last cursor and fills the final message after an earlier
|
||||
const transport: TeacherCloudTransport = {
|
||||
json: vi.fn(async (url) => {
|
||||
if (url === '/questions') return { request_id: 'question', run_id: 'one' };
|
||||
return ++reads < 3 ? { status: 'running' } : { status: 'completed', output: '最终建议' };
|
||||
return ++reads < 3
|
||||
? { status: 'running', thread_id: 'teacher-thread' }
|
||||
: { status: 'completed', output: '最终建议' };
|
||||
}),
|
||||
events: vi.fn(async (url, _signal, accept) => {
|
||||
const message = (id: string, content: string) => ({
|
||||
thread_id: 'teacher-thread',
|
||||
payload: { items: [{ stream_event: { type: 'message_delta', message_id: id, content } }] },
|
||||
});
|
||||
if (++streams === 1) {
|
||||
@@ -285,3 +288,62 @@ it('reconnects from the last cursor and fills the final message after an earlier
|
||||
expect(text.join('')).toBe('我先检查。\n\n最终建议');
|
||||
expect(f.progress).toHaveBeenCalledWith('连接中断,正在恢复老师回复…');
|
||||
});
|
||||
|
||||
it('keeps only the cloud main-thread answer while advancing past child events on reconnect', async () => {
|
||||
const f = await fixture();
|
||||
let reads = 0;
|
||||
let streams = 0;
|
||||
const text: string[] = [];
|
||||
const streamUrls: string[] = [];
|
||||
const transport: TeacherCloudTransport = {
|
||||
json: vi.fn(async (url) => {
|
||||
if (url === '/questions') return { request_id: 'question', run_id: 'one' };
|
||||
return ++reads < 3
|
||||
? { status: 'running', thread_id: 'teacher-thread' }
|
||||
: { status: 'completed', output: '老师最终答复' };
|
||||
}),
|
||||
events: vi.fn(async (url, _signal, accept) => {
|
||||
streamUrls.push(url);
|
||||
const message = (threadId: string, id: string, content: string) => ({
|
||||
thread_id: threadId,
|
||||
payload: { items: [{ stream_event: { type: 'message_delta', message_id: id, content } }] },
|
||||
});
|
||||
if (++streams === 1) {
|
||||
accept('message', message('teacher-thread', 'answer', '老师'), '1-0');
|
||||
accept('message', message('child-thread', 'child-answer', '子智能体内容'), '2-0');
|
||||
throw new Error('connection interrupted');
|
||||
}
|
||||
accept(
|
||||
'message',
|
||||
{
|
||||
thread_id: 'child-thread',
|
||||
payload: {
|
||||
chunk: {
|
||||
stream_event: {
|
||||
type: 'message_delta',
|
||||
message_id: 'child-answer',
|
||||
content: '子智能体后续内容',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'3-0'
|
||||
);
|
||||
accept('message', message('teacher-thread', 'answer', '最终答复'), '4-0');
|
||||
}),
|
||||
};
|
||||
await prepareCloudTeacher(
|
||||
f.account,
|
||||
f.topic,
|
||||
requestId,
|
||||
f.access,
|
||||
f.progress,
|
||||
f.saveRequest,
|
||||
transport
|
||||
).run([{ role: 'user', content: '检查' }], new AbortController().signal, (delta) =>
|
||||
text.push(delta)
|
||||
);
|
||||
expect(text.join('')).toBe('老师最终答复');
|
||||
expect(transport.events).toHaveBeenCalledTimes(2);
|
||||
expect(streamUrls[1]).toContain('after_seq=2-0');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user