fix(agent): add model request timeouts and empty-response fallback
This commit is contained in:
@@ -110,6 +110,43 @@ describe('NativeAgent', () => {
|
||||
const history = agent.getHistory();
|
||||
expect(history[history.length - 1]).toEqual({ role: 'assistant', content: 'Operation cancelled by user.' });
|
||||
});
|
||||
|
||||
it('returns fallback text when model response is empty', async () => {
|
||||
const mockClient: ModelClient = {
|
||||
chat: vi.fn().mockResolvedValue({
|
||||
content: '',
|
||||
stopReason: 'end_turn',
|
||||
usage: { inputTokens: 10, outputTokens: 5 },
|
||||
}),
|
||||
};
|
||||
|
||||
const agent = new NativeAgent({
|
||||
modelClient: mockClient,
|
||||
systemPrompt: 'You are helpful.',
|
||||
});
|
||||
|
||||
const response = await agent.process('Hi');
|
||||
expect(response).toBe('I could not generate a response for that. Please try again.');
|
||||
const history = agent.getHistory();
|
||||
expect(history[history.length - 1]).toEqual({
|
||||
role: 'assistant',
|
||||
content: 'I could not generate a response for that. Please try again.',
|
||||
});
|
||||
});
|
||||
|
||||
it('times out single-turn model calls', async () => {
|
||||
const mockClient: ModelClient = {
|
||||
chat: vi.fn().mockImplementation(() => new Promise<ChatResponse>(() => {})),
|
||||
};
|
||||
|
||||
const agent = new NativeAgent({
|
||||
modelClient: mockClient,
|
||||
systemPrompt: 'You are helpful.',
|
||||
modelTimeoutMs: 10,
|
||||
});
|
||||
|
||||
await expect(agent.process('Hi')).rejects.toThrow('Model request timed out after 10ms');
|
||||
});
|
||||
});
|
||||
|
||||
// Simple test tool
|
||||
@@ -611,4 +648,65 @@ describe('NativeAgent tool loop', () => {
|
||||
expect(response).toBe('Got both results');
|
||||
expect(mockClient.chat).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('returns fallback text when tool loop final response is empty', async () => {
|
||||
const mockClient: ModelClient = {
|
||||
chat: vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
content: '',
|
||||
stopReason: 'tool_use',
|
||||
usage: { inputTokens: 10, outputTokens: 5 },
|
||||
toolCalls: [{ id: 'call_1', name: 'test.echo', args: { text: 'hello' } }],
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
content: '',
|
||||
stopReason: 'end_turn',
|
||||
usage: { inputTokens: 12, outputTokens: 4 },
|
||||
}),
|
||||
};
|
||||
|
||||
const registry = new ToolRegistry();
|
||||
registry.register(echoTool);
|
||||
const hooks = new HookEngine({ confirm: [], log: [], silent: [] });
|
||||
const executor = new ToolExecutor(registry, hooks);
|
||||
|
||||
const agent = new NativeAgent({
|
||||
modelClient: mockClient,
|
||||
systemPrompt: 'You are helpful.',
|
||||
toolRegistry: registry,
|
||||
toolExecutor: executor,
|
||||
});
|
||||
|
||||
const response = await agent.process('echo hello');
|
||||
expect(response).toBe('I could not generate a response for that. Please try again.');
|
||||
const history = agent.getHistory();
|
||||
expect(history[history.length - 1]).toEqual({
|
||||
role: 'assistant',
|
||||
content: 'I could not generate a response for that. Please try again.',
|
||||
});
|
||||
});
|
||||
|
||||
it('times out tool-loop model calls and returns an error message', async () => {
|
||||
const mockClient: ModelClient = {
|
||||
chat: vi.fn().mockImplementation(() => new Promise<ChatResponse>(() => {})),
|
||||
};
|
||||
|
||||
const registry = new ToolRegistry();
|
||||
registry.register(echoTool);
|
||||
const hooks = new HookEngine({ confirm: [], log: [], silent: [] });
|
||||
const executor = new ToolExecutor(registry, hooks);
|
||||
|
||||
const agent = new NativeAgent({
|
||||
modelClient: mockClient,
|
||||
systemPrompt: 'You are helpful.',
|
||||
toolRegistry: registry,
|
||||
toolExecutor: executor,
|
||||
modelTimeoutMs: 10,
|
||||
});
|
||||
|
||||
const response = await agent.process('echo hello');
|
||||
expect(response).toContain('Error in tool loop');
|
||||
expect(response).toContain('Model request timed out after 10ms');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user