perf: 优化 Agent 流式会话处理

- 合并流式通知与持久化写入,限制浏览器会话缓存

- 增量投影轮次事件并稳定关联异步工具任务
This commit is contained in:
2026-07-27 19:41:11 +08:00
parent 5497931abd
commit b08eb009bb
10 changed files with 539 additions and 47 deletions

View File

@@ -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);
});
});