feat: add native agent with conversation history
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
export { NativeAgent, type NativeAgentConfig } from './native/index.js';
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
|
import { NativeAgent } from './agent.js';
|
||||||
|
import type { ModelClient, ChatResponse } from '../../models/types.js';
|
||||||
|
|
||||||
|
describe('NativeAgent', () => {
|
||||||
|
it('processes message and returns response', async () => {
|
||||||
|
const mockClient: ModelClient = {
|
||||||
|
chat: vi.fn().mockResolvedValue({
|
||||||
|
content: 'Hello! How can I help you?',
|
||||||
|
stopReason: 'end_turn',
|
||||||
|
usage: { inputTokens: 10, outputTokens: 8 },
|
||||||
|
} satisfies ChatResponse),
|
||||||
|
};
|
||||||
|
|
||||||
|
const agent = new NativeAgent({
|
||||||
|
modelClient: mockClient,
|
||||||
|
systemPrompt: 'You are Flynn, a helpful assistant.',
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await agent.process('Hello');
|
||||||
|
|
||||||
|
expect(response).toBe('Hello! How can I help you?');
|
||||||
|
expect(mockClient.chat).toHaveBeenCalledWith({
|
||||||
|
messages: [{ role: 'user', content: 'Hello' }],
|
||||||
|
system: 'You are Flynn, a helpful assistant.',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('maintains conversation history', async () => {
|
||||||
|
const mockClient: ModelClient = {
|
||||||
|
chat: vi.fn().mockResolvedValue({
|
||||||
|
content: 'Response',
|
||||||
|
stopReason: 'end_turn',
|
||||||
|
usage: { inputTokens: 10, outputTokens: 5 },
|
||||||
|
} satisfies ChatResponse),
|
||||||
|
};
|
||||||
|
|
||||||
|
const agent = new NativeAgent({
|
||||||
|
modelClient: mockClient,
|
||||||
|
systemPrompt: 'System',
|
||||||
|
});
|
||||||
|
|
||||||
|
await agent.process('First message');
|
||||||
|
await agent.process('Second message');
|
||||||
|
|
||||||
|
expect(mockClient.chat).toHaveBeenLastCalledWith({
|
||||||
|
messages: [
|
||||||
|
{ role: 'user', content: 'First message' },
|
||||||
|
{ role: 'assistant', content: 'Response' },
|
||||||
|
{ role: 'user', content: 'Second message' },
|
||||||
|
],
|
||||||
|
system: 'System',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resets conversation history', async () => {
|
||||||
|
const mockClient: ModelClient = {
|
||||||
|
chat: vi.fn().mockResolvedValue({
|
||||||
|
content: 'Response',
|
||||||
|
stopReason: 'end_turn',
|
||||||
|
usage: { inputTokens: 10, outputTokens: 5 },
|
||||||
|
} satisfies ChatResponse),
|
||||||
|
};
|
||||||
|
|
||||||
|
const agent = new NativeAgent({
|
||||||
|
modelClient: mockClient,
|
||||||
|
systemPrompt: 'System',
|
||||||
|
});
|
||||||
|
|
||||||
|
await agent.process('Message 1');
|
||||||
|
agent.reset();
|
||||||
|
await agent.process('Message 2');
|
||||||
|
|
||||||
|
expect(mockClient.chat).toHaveBeenLastCalledWith({
|
||||||
|
messages: [{ role: 'user', content: 'Message 2' }],
|
||||||
|
system: 'System',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import type { ModelClient, Message } from '../../models/types.js';
|
||||||
|
|
||||||
|
export interface NativeAgentConfig {
|
||||||
|
modelClient: ModelClient;
|
||||||
|
systemPrompt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class NativeAgent {
|
||||||
|
private modelClient: ModelClient;
|
||||||
|
private systemPrompt: string;
|
||||||
|
private history: Message[] = [];
|
||||||
|
|
||||||
|
constructor(config: NativeAgentConfig) {
|
||||||
|
this.modelClient = config.modelClient;
|
||||||
|
this.systemPrompt = config.systemPrompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
async process(userMessage: string): Promise<string> {
|
||||||
|
this.history.push({ role: 'user', content: userMessage });
|
||||||
|
|
||||||
|
const response = await this.modelClient.chat({
|
||||||
|
messages: [...this.history],
|
||||||
|
system: this.systemPrompt,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.history.push({ role: 'assistant', content: response.content });
|
||||||
|
|
||||||
|
return response.content;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(): void {
|
||||||
|
this.history = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getHistory(): Message[] {
|
||||||
|
return [...this.history];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { NativeAgent, type NativeAgentConfig } from './agent.js';
|
||||||
Reference in New Issue
Block a user