Initial commit.

This commit is contained in:
2025-11-04 05:17:27 +01:00
commit 3f979d2bbd
77 changed files with 10179 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
from .agent_roles import AgentRole, get_agent_role, list_agent_roles
from .agent_manager import AgentManager, AgentInstance
from .agent_communication import AgentMessage, AgentCommunicationBus
__all__ = ['AgentRole', 'get_agent_role', 'list_agent_roles', 'AgentManager', 'AgentInstance',
'AgentMessage', 'AgentCommunicationBus']
+157
View File
@@ -0,0 +1,157 @@
import sqlite3
import json
from typing import List, Optional
from dataclasses import dataclass
from enum import Enum
class MessageType(Enum):
REQUEST = "request"
RESPONSE = "response"
NOTIFICATION = "notification"
@dataclass
class AgentMessage:
message_id: str
from_agent: str
to_agent: str
message_type: MessageType
content: str
metadata: dict
timestamp: float
def to_dict(self) -> dict:
return {
'message_id': self.message_id,
'from_agent': self.from_agent,
'to_agent': self.to_agent,
'message_type': self.message_type.value,
'content': self.content,
'metadata': self.metadata,
'timestamp': self.timestamp
}
@classmethod
def from_dict(cls, data: dict) -> 'AgentMessage':
return cls(
message_id=data['message_id'],
from_agent=data['from_agent'],
to_agent=data['to_agent'],
message_type=MessageType(data['message_type']),
content=data['content'],
metadata=data['metadata'],
timestamp=data['timestamp']
)
class AgentCommunicationBus:
def __init__(self, db_path: str):
self.db_path = db_path
self.conn = sqlite3.connect(db_path)
self._create_tables()
def _create_tables(self):
cursor = self.conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS agent_messages (
message_id TEXT PRIMARY KEY,
from_agent TEXT,
to_agent TEXT,
message_type TEXT,
content TEXT,
metadata TEXT,
timestamp REAL,
session_id TEXT,
read INTEGER DEFAULT 0
)
''')
self.conn.commit()
def send_message(self, message: AgentMessage, session_id: Optional[str] = None):
cursor = self.conn.cursor()
cursor.execute('''
INSERT INTO agent_messages
(message_id, from_agent, to_agent, message_type, content, metadata, timestamp, session_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (
message.message_id,
message.from_agent,
message.to_agent,
message.message_type.value,
message.content,
json.dumps(message.metadata),
message.timestamp,
session_id
))
self.conn.commit()
def get_messages(self, agent_id: str, unread_only: bool = True) -> List[AgentMessage]:
cursor = self.conn.cursor()
if unread_only:
cursor.execute('''
SELECT message_id, from_agent, to_agent, message_type, content, metadata, timestamp
FROM agent_messages
WHERE to_agent = ? AND read = 0
ORDER BY timestamp ASC
''', (agent_id,))
else:
cursor.execute('''
SELECT message_id, from_agent, to_agent, message_type, content, metadata, timestamp
FROM agent_messages
WHERE to_agent = ?
ORDER BY timestamp ASC
''', (agent_id,))
messages = []
for row in cursor.fetchall():
messages.append(AgentMessage(
message_id=row[0],
from_agent=row[1],
to_agent=row[2],
message_type=MessageType(row[3]),
content=row[4],
metadata=json.loads(row[5]) if row[5] else {},
timestamp=row[6]
))
return messages
def mark_as_read(self, message_id: str):
cursor = self.conn.cursor()
cursor.execute('UPDATE agent_messages SET read = 1 WHERE message_id = ?', (message_id,))
self.conn.commit()
def clear_messages(self, session_id: Optional[str] = None):
cursor = self.conn.cursor()
if session_id:
cursor.execute('DELETE FROM agent_messages WHERE session_id = ?', (session_id,))
else:
cursor.execute('DELETE FROM agent_messages')
self.conn.commit()
def close(self):
self.conn.close()
def receive_messages(self, agent_id: str) -> List[AgentMessage]:
return self.get_messages(agent_id, unread_only=True)
def get_conversation_history(self, agent_a: str, agent_b: str) -> List[AgentMessage]:
cursor = self.conn.cursor()
cursor.execute('''
SELECT message_id, from_agent, to_agent, message_type, content, metadata, timestamp
FROM agent_messages
WHERE (from_agent = ? AND to_agent = ?) OR (from_agent = ? AND to_agent = ?)
ORDER BY timestamp ASC
''', (agent_a, agent_b, agent_b, agent_a))
messages = []
for row in cursor.fetchall():
messages.append(AgentMessage(
message_id=row[0],
from_agent=row[1],
to_agent=row[2],
message_type=MessageType(row[3]),
content=row[4],
metadata=json.loads(row[5]) if row[5] else {},
timestamp=row[6]
))
return messages
+186
View File
@@ -0,0 +1,186 @@
import time
import json
import uuid
from typing import Dict, List, Any, Optional, Callable
from dataclasses import dataclass, field
from .agent_roles import AgentRole, get_agent_role
from .agent_communication import AgentMessage, AgentCommunicationBus, MessageType
@dataclass
class AgentInstance:
agent_id: str
role: AgentRole
message_history: List[Dict[str, Any]] = field(default_factory=list)
context: Dict[str, Any] = field(default_factory=dict)
created_at: float = field(default_factory=time.time)
task_count: int = 0
def add_message(self, role: str, content: str):
self.message_history.append({
'role': role,
'content': content,
'timestamp': time.time()
})
def get_system_message(self) -> Dict[str, str]:
return {'role': 'system', 'content': self.role.system_prompt}
def get_messages_for_api(self) -> List[Dict[str, str]]:
return [self.get_system_message()] + [
{'role': msg['role'], 'content': msg['content']}
for msg in self.message_history
]
class AgentManager:
def __init__(self, db_path: str, api_caller: Callable):
self.db_path = db_path
self.api_caller = api_caller
self.communication_bus = AgentCommunicationBus(db_path)
self.active_agents: Dict[str, AgentInstance] = {}
self.session_id = str(uuid.uuid4())[:16]
def create_agent(self, role_name: str, agent_id: Optional[str] = None) -> str:
if agent_id is None:
agent_id = f"{role_name}_{str(uuid.uuid4())[:8]}"
role = get_agent_role(role_name)
agent = AgentInstance(
agent_id=agent_id,
role=role
)
self.active_agents[agent_id] = agent
return agent_id
def get_agent(self, agent_id: str) -> Optional[AgentInstance]:
return self.active_agents.get(agent_id)
def remove_agent(self, agent_id: str) -> bool:
if agent_id in self.active_agents:
del self.active_agents[agent_id]
return True
return False
def execute_agent_task(self, agent_id: str, task: str, context: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
agent = self.get_agent(agent_id)
if not agent:
return {'error': f'Agent {agent_id} not found'}
if context:
agent.context.update(context)
agent.add_message('user', task)
agent.task_count += 1
messages = agent.get_messages_for_api()
try:
response = self.api_caller(
messages=messages,
temperature=agent.role.temperature,
max_tokens=agent.role.max_tokens
)
if response and 'choices' in response:
assistant_message = response['choices'][0]['message']['content']
agent.add_message('assistant', assistant_message)
return {
'success': True,
'agent_id': agent_id,
'response': assistant_message,
'role': agent.role.name,
'task_count': agent.task_count
}
else:
return {'error': 'Invalid API response', 'agent_id': agent_id}
except Exception as e:
return {'error': str(e), 'agent_id': agent_id}
def send_agent_message(self, from_agent_id: str, to_agent_id: str,
content: str, message_type: MessageType = MessageType.REQUEST,
metadata: Optional[Dict[str, Any]] = None):
message = AgentMessage(
from_agent=from_agent_id,
to_agent=to_agent_id,
message_type=message_type,
content=content,
metadata=metadata or {},
timestamp=time.time(),
message_id=str(uuid.uuid4())[:16]
)
self.communication_bus.send_message(message, self.session_id)
return message.message_id
def get_agent_messages(self, agent_id: str, unread_only: bool = True) -> List[AgentMessage]:
return self.communication_bus.get_messages(agent_id, unread_only)
def collaborate_agents(self, orchestrator_id: str, task: str, agent_roles: List[str]):
orchestrator = self.get_agent(orchestrator_id)
if not orchestrator:
orchestrator_id = self.create_agent('orchestrator')
orchestrator = self.get_agent(orchestrator_id)
worker_agents = []
for role in agent_roles:
agent_id = self.create_agent(role)
worker_agents.append({
'agent_id': agent_id,
'role': role
})
orchestration_prompt = f'''Task: {task}
Available specialized agents:
{chr(10).join([f"- {a['agent_id']} ({a['role']})" for a in worker_agents])}
Break down the task and delegate subtasks to appropriate agents. Coordinate their work and integrate results.'''
orchestrator_result = self.execute_agent_task(orchestrator_id, orchestration_prompt)
results = {
'orchestrator': orchestrator_result,
'agents': []
}
for agent_info in worker_agents:
agent_id = agent_info['agent_id']
messages = self.get_agent_messages(agent_id)
for msg in messages:
subtask = msg.content
result = self.execute_agent_task(agent_id, subtask)
results['agents'].append(result)
self.send_agent_message(
from_agent_id=agent_id,
to_agent_id=orchestrator_id,
content=result.get('response', ''),
message_type=MessageType.RESPONSE
)
self.communication_bus.mark_as_read(msg.message_id)
return results
def get_session_summary(self) -> Dict[str, Any]:
summary = {
'session_id': self.session_id,
'active_agents': len(self.active_agents),
'agents': [
{
'agent_id': agent_id,
'role': agent.role.name,
'task_count': agent.task_count,
'message_count': len(agent.message_history)
}
for agent_id, agent in self.active_agents.items()
]
}
return summary
def clear_session(self):
self.active_agents.clear()
self.communication_bus.clear_messages(session_id=self.session_id)
self.session_id = str(uuid.uuid4())[:16]
+192
View File
@@ -0,0 +1,192 @@
from dataclasses import dataclass
from typing import List, Dict, Any, Set
@dataclass
class AgentRole:
name: str
description: str
system_prompt: str
allowed_tools: Set[str]
specialization_areas: List[str]
temperature: float = 0.7
max_tokens: int = 4096
AGENT_ROLES = {
'coding': AgentRole(
name='coding',
description='Specialized in writing, reviewing, and debugging code',
system_prompt='''You are a coding specialist AI assistant. Your primary responsibilities:
- Write clean, efficient, well-structured code
- Review code for bugs, security issues, and best practices
- Refactor and optimize existing code
- Implement features based on specifications
- Follow language-specific conventions and patterns
Focus on code quality, maintainability, and performance.''',
allowed_tools={
'read_file', 'write_file', 'list_directory', 'create_directory',
'change_directory', 'get_current_directory', 'python_exec',
'run_command', 'index_directory'
},
specialization_areas=['code_writing', 'code_review', 'debugging', 'refactoring'],
temperature=0.3
),
'research': AgentRole(
name='research',
description='Specialized in information gathering and analysis',
system_prompt='''You are a research specialist AI assistant. Your primary responsibilities:
- Search for and gather relevant information
- Analyze data and documentation
- Synthesize findings into clear summaries
- Verify facts and cross-reference sources
- Identify trends and patterns in information
Focus on accuracy, thoroughness, and clear communication of findings.''',
allowed_tools={
'read_file', 'list_directory', 'index_directory',
'http_fetch', 'web_search', 'web_search_news',
'db_query', 'db_get'
},
specialization_areas=['information_gathering', 'analysis', 'documentation', 'fact_checking'],
temperature=0.5
),
'data_analysis': AgentRole(
name='data_analysis',
description='Specialized in data processing and analysis',
system_prompt='''You are a data analysis specialist AI assistant. Your primary responsibilities:
- Process and analyze structured and unstructured data
- Perform statistical analysis and pattern recognition
- Query databases and extract insights
- Create data summaries and reports
- Identify anomalies and trends
Focus on accuracy, data integrity, and actionable insights.''',
allowed_tools={
'db_query', 'db_get', 'db_set', 'read_file', 'write_file',
'python_exec', 'run_command', 'list_directory'
},
specialization_areas=['data_processing', 'statistical_analysis', 'database_operations'],
temperature=0.3
),
'planning': AgentRole(
name='planning',
description='Specialized in task planning and coordination',
system_prompt='''You are a planning specialist AI assistant. Your primary responsibilities:
- Break down complex tasks into manageable steps
- Create execution plans and workflows
- Identify dependencies and prerequisites
- Estimate effort and resource requirements
- Coordinate between different components
Focus on logical organization, completeness, and feasibility.''',
allowed_tools={
'read_file', 'write_file', 'list_directory', 'index_directory',
'db_set', 'db_get'
},
specialization_areas=['task_decomposition', 'workflow_design', 'coordination'],
temperature=0.6
),
'testing': AgentRole(
name='testing',
description='Specialized in testing and quality assurance',
system_prompt='''You are a testing specialist AI assistant. Your primary responsibilities:
- Design and execute test cases
- Identify edge cases and potential failures
- Verify functionality and correctness
- Test error handling and edge conditions
- Ensure code meets quality standards
Focus on thoroughness, coverage, and issue identification.''',
allowed_tools={
'read_file', 'write_file', 'python_exec', 'run_command',
'list_directory', 'db_query'
},
specialization_areas=['test_design', 'quality_assurance', 'validation'],
temperature=0.4
),
'documentation': AgentRole(
name='documentation',
description='Specialized in creating and maintaining documentation',
system_prompt='''You are a documentation specialist AI assistant. Your primary responsibilities:
- Write clear, comprehensive documentation
- Create API references and user guides
- Document code with comments and docstrings
- Organize and structure information logically
- Ensure documentation is up-to-date and accurate
Focus on clarity, completeness, and user-friendliness.''',
allowed_tools={
'read_file', 'write_file', 'list_directory', 'index_directory',
'http_fetch', 'web_search'
},
specialization_areas=['technical_writing', 'documentation_organization', 'user_guides'],
temperature=0.6
),
'orchestrator': AgentRole(
name='orchestrator',
description='Coordinates multiple agents and manages overall execution',
system_prompt='''You are an orchestrator AI assistant. Your primary responsibilities:
- Coordinate multiple specialized agents
- Delegate tasks to appropriate agents
- Integrate results from different agents
- Manage overall workflow execution
- Ensure task completion and quality
Focus on effective delegation, integration, and overall success.''',
allowed_tools={
'read_file', 'write_file', 'list_directory', 'db_set', 'db_get', 'db_query'
},
specialization_areas=['agent_coordination', 'task_delegation', 'result_integration'],
temperature=0.5
),
'general': AgentRole(
name='general',
description='General purpose agent for miscellaneous tasks',
system_prompt='''You are a general purpose AI assistant. Your responsibilities:
- Handle diverse tasks across multiple domains
- Provide balanced assistance for various needs
- Adapt to different types of requests
- Collaborate with specialized agents when needed
Focus on versatility, helpfulness, and task completion.''',
allowed_tools={
'read_file', 'write_file', 'list_directory', 'create_directory',
'change_directory', 'get_current_directory', 'python_exec',
'run_command', 'run_command_interactive', 'http_fetch',
'web_search', 'web_search_news', 'db_set', 'db_get', 'db_query',
'index_directory'
},
specialization_areas=['general_assistance'],
temperature=0.7
)
}
def get_agent_role(role_name: str) -> AgentRole:
return AGENT_ROLES.get(role_name, AGENT_ROLES['general'])
def list_agent_roles() -> Dict[str, AgentRole]:
return AGENT_ROLES.copy()
def get_recommended_agent(task_description: str) -> str:
task_lower = task_description.lower()
code_keywords = ['code', 'implement', 'function', 'class', 'bug', 'debug', 'refactor', 'optimize']
research_keywords = ['search', 'find', 'research', 'information', 'analyze', 'investigate']
data_keywords = ['data', 'database', 'query', 'statistics', 'analyze', 'process']
planning_keywords = ['plan', 'organize', 'workflow', 'steps', 'coordinate']
testing_keywords = ['test', 'verify', 'validate', 'check', 'quality']
doc_keywords = ['document', 'documentation', 'explain', 'guide', 'manual']
if any(keyword in task_lower for keyword in code_keywords):
return 'coding'
elif any(keyword in task_lower for keyword in research_keywords):
return 'research'
elif any(keyword in task_lower for keyword in data_keywords):
return 'data_analysis'
elif any(keyword in task_lower for keyword in planning_keywords):
return 'planning'
elif any(keyword in task_lower for keyword in testing_keywords):
return 'testing'
elif any(keyword in task_lower for keyword in doc_keywords):
return 'documentation'
else:
return 'general'