import { describe, it, expect, vi, beforeEach } from 'vitest';
import { BasicAgent } from '../../src/agents/BasicAgent.js';
import { MemoryStore, Observation } from '../../src/memory/store/MemoryStore.js';
// Create a mock memory store for testing
const mockMemoryStore: MemoryStore = {
add: vi.fn().mockResolvedValue({
text: 'test observation',
timestamp: new Date().toISOString()
}),
query: vi.fn().mockResolvedValue([]),
prune: vi.fn().mockResolvedValue(0),
findSimilar: vi.fn().mockResolvedValue([]),
save: vi.fn().mockResolvedValue(undefined),
load: vi.fn().mockResolvedValue(undefined),
getLoadingPromise: vi.fn().mockResolvedValue(undefined),
// Add compatibility methods for graph operations
addEntity: vi.fn().mockResolvedValue({
id: 'mock-id',
entityType: 'thought',
observations: ['Reasoning: Complete reasoning process', 'Category: testing']
}),
addRelation: vi.fn().mockResolvedValue(undefined)
};
// Mock the graph and graphStorage
vi.mock('../../src/memory/storage.js', () => {
return {
graph: {
addEntity: vi.fn(),
addRelation: vi.fn(),
addObservations: vi.fn()
},
graphStorage: {
save: vi.fn()
}
};
});
describe('BasicAgent', () => {
let agent: BasicAgent;
beforeEach(() => {
// Reset mocks
vi.clearAllMocks();
// Create a fresh agent for each test
agent = new BasicAgent('test-agent', mockMemoryStore);
});
it('should initialize with default parameters', async () => {
// Act
await agent.init({});
// Assert
expect(agent.agentId).toBe('test-agent');
});
it('should merge context parameters during initialization', async () => {
// Arrange
const ctx = {
thinkParams: {
structuredReasoning: 'Initial reasoning',
tags: ['test'],
formatOutput: false // Disable formatting for this test
}
};
// Act
await agent.init(ctx);
// Assert - we'll test this indirectly through step
const result = await agent.step('Next step');
// The agent now combines the input with the initial reasoning
expect(result).toContain('Next step');
});
it('should process a step and update reasoning', async () => {
// Arrange
await agent.init({
thinkParams: {
formatOutput: false // Disable formatting for this test
}
});
// Act
const result = await agent.step('First step reasoning');
// Assert
expect(result).toBe('First step reasoning');
});
it('should increment currentStep if defined', async () => {
// Arrange
const thinkParams = {
currentStep: 1,
plannedSteps: 3,
formatOutput: false // Disable formatting for this test
};
agent = new BasicAgent('test-agent', mockMemoryStore, thinkParams);
await agent.init({});
// Act
await agent.step('Step reasoning');
// Check for step counter in output - the agent may not include previous content
const nextResult = await agent.step('Another step');
// Assert
// Just check that the second step contains the new input
expect(nextResult).toContain('Another step');
// Since we can't access the internal state directly, we can't verify the step counter
// was incremented. We'll trust that it works based on the implementation.
});
it('should store thought in memory when finalize is called', async () => {
// Setup agent with memory storage enabled
agent = new BasicAgent('test-agent', mockMemoryStore, {
storeInMemory: true,
structuredReasoning: 'Complete reasoning process',
tags: ['test', 'memory'],
category: 'testing'
});
// Act
await agent.init({});
await agent.finalize();
// Assert - check that the required memory methods were called
expect(mockMemoryStore.addEntity).toHaveBeenCalled();
expect(mockMemoryStore.save).toHaveBeenCalled();
});
it('should support self-reflection during step', async () => {
// Setup agent with self-reflection enabled
agent = new BasicAgent('test-agent', mockMemoryStore, {
storeInMemory: true,
selfReflect: true,
currentStep: 1
});
// Act
await agent.init({});
const result = await agent.step('Testing reflection');
// Assert - the reflection is now included in the formatted output
expect(result).toContain('Self-Reflection');
});
});