perf: 优化 Agent 流式会话处理
- 合并流式通知与持久化写入,限制浏览器会话缓存 - 增量投影轮次事件并稳定关联异步工具任务
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { useUserStore } from '@easyflow/stores';
|
||||
|
||||
@@ -23,6 +23,10 @@ describe('agentChatRuntimeManager', () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('replaces draft image URLs and isolates snapshots by account', async () => {
|
||||
let callbacks: any;
|
||||
vi.mocked(sendAgentChat).mockImplementation((_data, options) => {
|
||||
@@ -95,4 +99,76 @@ describe('agentChatRuntimeManager', () => {
|
||||
userStore.setUserInfo(firstAccount);
|
||||
expect(agentChatRuntimeManager.getSnapshot('101')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('coalesces streaming notifications and persists terminal state immediately', async () => {
|
||||
vi.useFakeTimers();
|
||||
let callbacks: any;
|
||||
vi.mocked(sendAgentChat).mockImplementation((_data, options) => {
|
||||
callbacks = options;
|
||||
return Promise.resolve() as any;
|
||||
});
|
||||
const account = {
|
||||
avatar: '',
|
||||
id: 'stream-user',
|
||||
loginName: 'stream-user',
|
||||
nickname: '流式用户',
|
||||
tenantId: 'tenant-1',
|
||||
};
|
||||
useUserStore().setUserInfo(account);
|
||||
|
||||
await agentChatRuntimeManager.start({
|
||||
agentId: 'agent-1',
|
||||
prompt: '流式测试',
|
||||
sessionId: 'stream-session',
|
||||
});
|
||||
const listener = vi.fn();
|
||||
const unsubscribe = agentChatRuntimeManager.subscribe(listener);
|
||||
const storageSpy = vi.spyOn(sessionStorage, 'setItem');
|
||||
|
||||
for (const delta of ['A', 'B', 'C']) {
|
||||
callbacks.onMessage({
|
||||
data: JSON.stringify({
|
||||
domain: 'LLM',
|
||||
payload: { delta },
|
||||
type: 'MESSAGE',
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
expect(listener).not.toHaveBeenCalled();
|
||||
expect(storageSpy).not.toHaveBeenCalled();
|
||||
expect(
|
||||
JSON.stringify(
|
||||
agentChatRuntimeManager.getSnapshot('stream-session')?.items,
|
||||
),
|
||||
).toContain('ABC');
|
||||
|
||||
await vi.advanceTimersByTimeAsync(50);
|
||||
expect(listener).toHaveBeenCalledTimes(1);
|
||||
expect(storageSpy).not.toHaveBeenCalled();
|
||||
|
||||
await vi.advanceTimersByTimeAsync(250);
|
||||
expect(storageSpy).toHaveBeenCalledTimes(2);
|
||||
|
||||
callbacks.onMessage({
|
||||
data: JSON.stringify({
|
||||
domain: 'LLM',
|
||||
payload: { delta: 'D' },
|
||||
type: 'MESSAGE',
|
||||
}),
|
||||
});
|
||||
listener.mockClear();
|
||||
storageSpy.mockClear();
|
||||
callbacks.onFinished();
|
||||
|
||||
expect(listener).toHaveBeenCalledTimes(1);
|
||||
expect(storageSpy).toHaveBeenCalledTimes(2);
|
||||
expect(agentChatRuntimeManager.getSnapshot('stream-session')).toEqual(
|
||||
expect.objectContaining({ completed: true, sending: false }),
|
||||
);
|
||||
|
||||
unsubscribe();
|
||||
storageSpy.mockRestore();
|
||||
clearAgentChatBrowserCache(account);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user