Skip to content

Commit a830588

Browse files
committed
fix: Add missing maxHistorySize parameter in streaming conversation save
The processStreamInBackground method was not passing the MAX_MESSAGE_PAIRS_PER_AGENT parameter to saveConversationExchange, while the non-streaming code path correctly included it. This inconsistency could lead to unlimited message history growth in streaming scenarios. Changes: - Add missing maxHistorySize parameter to saveConversationExchange call in processStreamInBackground - Add unit test to verify streaming responses save conversation history with correct maxHistorySize - Test ensures the bug is fixed and prevents regression This fix ensures that conversation history is properly limited in streaming scenarios, preventing potential memory issues from unlimited message accumulation.
1 parent 75a1e82 commit a830588

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

typescript/src/orchestrator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,8 @@ export class AgentSquad {
484484
this.storage,
485485
userId,
486486
sessionId,
487-
agent.id
487+
agent.id,
488+
this.config.MAX_MESSAGE_PAIRS_PER_AGENT
488489
);
489490
}
490491

typescript/tests/Orchestrator.test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,87 @@ describe('AgentSquad', () => {
156156
expect(response.output).toBe(mockAccumulatorTransform);
157157
});
158158

159+
test('streaming response saves conversation history with maxHistorySize', async () => {
160+
// Create a custom orchestrator with specific MAX_MESSAGE_PAIRS_PER_AGENT
161+
const customOrchestrator = new AgentSquad({
162+
storage: mockStorage,
163+
classifier: mockClassifier,
164+
config: {
165+
LOG_EXECUTION_TIMES: true,
166+
USE_DEFAULT_AGENT_IF_NONE_IDENTIFIED: true,
167+
MAX_MESSAGE_PAIRS_PER_AGENT: 10,
168+
},
169+
});
170+
171+
const userInput = 'Test streaming save';
172+
const userId = 'user1';
173+
const sessionId = 'session1';
174+
175+
const mockAgent = {
176+
id: 'test-agent',
177+
name: 'Test Agent',
178+
description: 'A test agent',
179+
processRequest: jest.fn(),
180+
saveChat: true,
181+
} as unknown as jest.Mocked<Agent>;
182+
183+
customOrchestrator.addAgent(mockAgent);
184+
185+
const mockClassifierResult: ClassifierResult = {
186+
selectedAgent: mockAgent,
187+
confidence: 0.9,
188+
};
189+
190+
mockClassifier.classify.mockResolvedValue(mockClassifierResult);
191+
192+
const mockStream = (async function* () {
193+
yield 'Hello';
194+
yield ' world';
195+
yield '!';
196+
})();
197+
198+
mockAgent.processRequest.mockResolvedValue(mockStream);
199+
200+
// Mock the AccumulatorTransform to simulate streaming completion
201+
const mockAccumulatorTransform = {
202+
getAccumulatedData: jest.fn().mockReturnValue('Hello world!'),
203+
on: jest.fn().mockImplementation((event, handler) => {
204+
if (event === 'finish') {
205+
// Simulate stream finishing after a short delay
206+
setTimeout(() => handler(), 10);
207+
}
208+
return mockAccumulatorTransform;
209+
}),
210+
write: jest.fn().mockReturnValue(true),
211+
end: jest.fn(),
212+
destroy: jest.fn(),
213+
pipe: jest.fn(),
214+
unpipe: jest.fn(),
215+
removeListener: jest.fn(),
216+
};
217+
218+
(AccumulatorTransform as jest.MockedClass<typeof AccumulatorTransform>).mockImplementation(() => mockAccumulatorTransform as any);
219+
220+
// Mock storage methods
221+
mockStorage.fetchAllChats.mockResolvedValue([]);
222+
223+
const response = await customOrchestrator.routeRequest(userInput, userId, sessionId);
224+
225+
// Wait for the stream to finish processing
226+
await new Promise(resolve => setTimeout(resolve, 50));
227+
228+
// Verify that saveConversationExchange was called with the correct parameters
229+
expect(chatUtils.saveConversationExchange).toHaveBeenCalledWith(
230+
userInput,
231+
'Hello world!',
232+
mockStorage,
233+
userId,
234+
sessionId,
235+
mockAgent.id,
236+
10 // MAX_MESSAGE_PAIRS_PER_AGENT from config
237+
);
238+
});
239+
159240
test('setDefaultAgent changes the default agent', () => {
160241
const newDefaultAgent: Agent = {
161242
id: 'new-default',

0 commit comments

Comments
 (0)