diff --git a/README.md b/README.md index ba5e50d..270dfb5 100644 --- a/README.md +++ b/README.md @@ -65,17 +65,25 @@ SimpleAgent is organized in a modular structure: ``` SimpleAgent/ ├── core/ # Core framework components -│ ├── agent.py # Main SimpleAgent class -│ ├── run_manager.py # Execution loop management -│ ├── execution.py # Command execution and step management -│ ├── tool_manager.py # Dynamic tool loading system -│ ├── conversation.py # Conversation history management -│ ├── memory.py # Persistent memory system -│ ├── security.py # Security and path validation -│ ├── loop_detector.py # Loop detection and breaking -│ ├── summarizer.py # Change summarization -│ ├── config.py # Configuration management -│ └── version.py # Version and changelog tracking +│ ├── agent/ # Agent interface and run loop +│ │ ├── agent.py # Main SimpleAgent class +│ │ └── run_manager.py # Execution loop management +│ ├── execution/ # Command execution and tool management +│ │ ├── execution.py # Command execution and step management +│ │ ├── tool_manager.py # Dynamic tool loading system +│ │ └── summarizer.py # Change summarization +│ ├── conversation/ # Conversation and memory management +│ │ ├── conversation.py # Conversation history management +│ │ └── memory.py # Persistent memory system +│ ├── metacognition/ # Metacognition, prompts, and loop detection +│ │ ├── metacognition.py # Internal monologue and reflection +│ │ ├── loop_detector.py # Loop detection and breaking +│ │ └── prompts.py # Centralized prompt templates +│ ├── utils/ # Utilities and configuration +│ │ ├── security.py # Security and path validation +│ │ ├── config.py # Configuration management +│ │ └── version.py # Version and changelog tracking +│ └── __init__.py # Core package exports ├── commands/ # Local command modules (optional) │ └── __init__.py # Command registration system ├── output/ # Generated files and session data diff --git a/SimpleAgent/SimpleAgent.py b/SimpleAgent/SimpleAgent.py index f09e66c..bdac698 100644 --- a/SimpleAgent/SimpleAgent.py +++ b/SimpleAgent/SimpleAgent.py @@ -25,9 +25,9 @@ from commands import REGISTERED_COMMANDS, COMMAND_SCHEMAS # Import core modules -from core.agent import SimpleAgent -from core.config import OPENAI_API_KEY, MAX_STEPS, API_PROVIDER, API_BASE_URL, GEMINI_API_KEY, create_client -from core.version import AGENT_VERSION +from core.agent.agent import SimpleAgent +from core.utils.config import OPENAI_API_KEY, MAX_STEPS, API_PROVIDER, API_BASE_URL, GEMINI_API_KEY, create_client +from core.utils.version import AGENT_VERSION # Commands will be initialized in main() based on user preference diff --git a/SimpleAgent/commands/__init__.py b/SimpleAgent/commands/__init__.py index 9e4576a..d0c9e44 100644 --- a/SimpleAgent/commands/__init__.py +++ b/SimpleAgent/commands/__init__.py @@ -4,12 +4,12 @@ This package contains all the commands that SimpleAgent can execute. Commands are organized by category in subdirectories. -This module now uses the new ToolManager from core.tool_manager to handle +This module now uses the new ToolManager from core.execution.tool_manager to handle both local and remote (GitHub) tools with dynamic loading support. """ # Import the new tool manager -from core.tool_manager import ( +from core.execution.tool_manager import ( REGISTERED_COMMANDS, COMMAND_SCHEMAS, register_command, diff --git a/SimpleAgent/core/__init__.py b/SimpleAgent/core/__init__.py index 72b500b..39d8c76 100644 --- a/SimpleAgent/core/__init__.py +++ b/SimpleAgent/core/__init__.py @@ -4,13 +4,13 @@ This package contains the core components of the SimpleAgent system. """ -from core.agent import SimpleAgent -from core.summarizer import ChangeSummarizer -from core.conversation import ConversationManager -from core.execution import ExecutionManager -from core.memory import MemoryManager -from core.run_manager import RunManager -from core.security import get_secure_path +from core.agent.agent import SimpleAgent +from core.execution.summarizer import ChangeSummarizer +from core.conversation.conversation import ConversationManager +from core.execution.execution import ExecutionManager +from core.conversation.memory import MemoryManager +from core.agent.run_manager import RunManager +from core.utils.security import get_secure_path __all__ = [ "SimpleAgent", diff --git a/SimpleAgent/core/agent/__init__.py b/SimpleAgent/core/agent/__init__.py new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/SimpleAgent/core/agent/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SimpleAgent/core/agent.py b/SimpleAgent/core/agent/agent.py similarity index 93% rename from SimpleAgent/core/agent.py rename to SimpleAgent/core/agent/agent.py index 8c4c210..e0c0d0c 100644 --- a/SimpleAgent/core/agent.py +++ b/SimpleAgent/core/agent/agent.py @@ -14,12 +14,12 @@ import os from typing import List, Dict, Any, Optional -from core.conversation import ConversationManager -from core.execution import ExecutionManager -from core.memory import MemoryManager -from core.run_manager import RunManager -from core.security import get_secure_path -from core.config import DEFAULT_MODEL, OUTPUT_DIR +from core.conversation.conversation import ConversationManager +from core.execution.execution import ExecutionManager +from core.conversation.memory import MemoryManager +from core.agent.run_manager import RunManager +from core.utils.security import get_secure_path +from core.utils.config import DEFAULT_MODEL, OUTPUT_DIR class SimpleAgent: diff --git a/SimpleAgent/core/run_manager.py b/SimpleAgent/core/agent/run_manager.py similarity index 98% rename from SimpleAgent/core/run_manager.py rename to SimpleAgent/core/agent/run_manager.py index 8ec81a4..788c37b 100644 --- a/SimpleAgent/core/run_manager.py +++ b/SimpleAgent/core/agent/run_manager.py @@ -13,14 +13,14 @@ import json from typing import List, Dict, Any, Optional -from core.conversation import ConversationManager -from core.execution import ExecutionManager -from core.memory import MemoryManager -from core.summarizer import ChangeSummarizer -from core.loop_detector import LoopDetector -from core.metacognition import MetaCognition -from core.prompts import prompts -from core.config import OUTPUT_DIR +from core.conversation.conversation import ConversationManager +from core.execution.execution import ExecutionManager +from core.conversation.memory import MemoryManager +from core.execution.summarizer import ChangeSummarizer +from core.metacognition.loop_detector import LoopDetector +from core.metacognition.metacognition import MetaCognition +from core.metacognition.prompts import prompts +from core.utils.config import OUTPUT_DIR class RunManager: diff --git a/SimpleAgent/core/conversation/__init__.py b/SimpleAgent/core/conversation/__init__.py new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/SimpleAgent/core/conversation/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SimpleAgent/core/conversation.py b/SimpleAgent/core/conversation/conversation.py similarity index 100% rename from SimpleAgent/core/conversation.py rename to SimpleAgent/core/conversation/conversation.py diff --git a/SimpleAgent/core/memory.py b/SimpleAgent/core/conversation/memory.py similarity index 98% rename from SimpleAgent/core/memory.py rename to SimpleAgent/core/conversation/memory.py index 4c7fc3a..f7940a9 100644 --- a/SimpleAgent/core/memory.py +++ b/SimpleAgent/core/conversation/memory.py @@ -9,7 +9,7 @@ import json from typing import Dict, Any, List -from core.config import MEMORY_FILE, OUTPUT_DIR +from core.utils.config import MEMORY_FILE, OUTPUT_DIR class MemoryManager: diff --git a/SimpleAgent/core/execution/__init__.py b/SimpleAgent/core/execution/__init__.py new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/SimpleAgent/core/execution/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SimpleAgent/core/execution.py b/SimpleAgent/core/execution/execution.py similarity index 98% rename from SimpleAgent/core/execution.py rename to SimpleAgent/core/execution/execution.py index 35882c6..8ccf42c 100644 --- a/SimpleAgent/core/execution.py +++ b/SimpleAgent/core/execution/execution.py @@ -10,9 +10,9 @@ import inspect from typing import Dict, Any, List, Optional, Tuple, Callable -from core.tool_manager import REGISTERED_COMMANDS, COMMAND_SCHEMAS, load_tool -from core.security import get_secure_path -from core.config import OUTPUT_DIR, DEFAULT_MODEL, create_client, API_PROVIDER +from core.execution.tool_manager import REGISTERED_COMMANDS, COMMAND_SCHEMAS, load_tool +from core.utils.security import get_secure_path +from core.utils.config import OUTPUT_DIR, DEFAULT_MODEL, create_client, API_PROVIDER class ExecutionManager: diff --git a/SimpleAgent/core/summarizer.py b/SimpleAgent/core/execution/summarizer.py similarity index 98% rename from SimpleAgent/core/summarizer.py rename to SimpleAgent/core/execution/summarizer.py index cd2fcd6..51af927 100644 --- a/SimpleAgent/core/summarizer.py +++ b/SimpleAgent/core/execution/summarizer.py @@ -7,7 +7,7 @@ import os from typing import List, Dict, Any -from core.config import SUMMARIZER_MODEL, create_client +from core.utils.config import SUMMARIZER_MODEL, create_client class ChangeSummarizer: diff --git a/SimpleAgent/core/tool_manager.py b/SimpleAgent/core/execution/tool_manager.py similarity index 91% rename from SimpleAgent/core/tool_manager.py rename to SimpleAgent/core/execution/tool_manager.py index 9b8180c..4ebc1e9 100644 --- a/SimpleAgent/core/tool_manager.py +++ b/SimpleAgent/core/execution/tool_manager.py @@ -24,9 +24,10 @@ from dataclasses import dataclass, field import ast import re +import pathlib # Import GitHub token from config -from core.config import GITHUB_TOKEN +from core.utils.config import GITHUB_TOKEN # Global registries REGISTERED_COMMANDS: Dict[str, Callable] = {} @@ -72,6 +73,7 @@ def initialize(self) -> None: """Initialize the tool manager by discovering available tools.""" self.logger.info("🚀 Initializing Tool Manager...") self._create_temp_directory() + self._discover_local_tools() self._discover_tools() self._register_tool_schemas() self.logger.info(f"✅ Discovered {len(self.tools)} tools") @@ -82,6 +84,35 @@ def _create_temp_directory(self) -> None: # Add to Python path sys.path.insert(0, self.temp_dir) + def _discover_local_tools(self): + """Discover all available tools from the local commands directory.""" + base_dir = pathlib.Path(__file__).parent.parent / 'commands' + if not base_dir.exists(): + return + for category_dir in base_dir.iterdir(): + if not category_dir.is_dir() or category_dir.name.startswith('__'): + continue + for tool_dir in category_dir.iterdir(): + if not tool_dir.is_dir() or tool_dir.name.startswith('__'): + continue + init_file = tool_dir / '__init__.py' + if not init_file.exists(): + continue + module_name = f"commands.{category_dir.name}.{tool_dir.name}" + if module_name in sys.modules: + continue + try: + importlib.import_module(module_name) + tool = Tool( + name=tool_dir.name, + category=category_dir.name, + github_path=None + ) + self.tools[tool_dir.name] = tool + self.logger.debug(f"Discovered local tool: {tool_dir.name} in {category_dir.name}") + except Exception as e: + self.logger.error(f"Failed to import local tool {module_name}: {e}") + def _discover_tools(self) -> None: """Discover all available tools from GitHub repository.""" try: diff --git a/SimpleAgent/core/metacognition/__init__.py b/SimpleAgent/core/metacognition/__init__.py new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/SimpleAgent/core/metacognition/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SimpleAgent/core/loop_detector.py b/SimpleAgent/core/metacognition/loop_detector.py similarity index 98% rename from SimpleAgent/core/loop_detector.py rename to SimpleAgent/core/metacognition/loop_detector.py index 268d473..176bfec 100644 --- a/SimpleAgent/core/loop_detector.py +++ b/SimpleAgent/core/metacognition/loop_detector.py @@ -16,7 +16,7 @@ class LoopDetector: to help break out of unproductive patterns. Loop breaking messages are generated by the centralized prompt system - in core.prompts for better maintainability. Use generate_breaking_message() + in core.metacognition.prompts for better maintainability. Use generate_breaking_message() to create intervention messages. """ @@ -175,7 +175,7 @@ def generate_breaking_message(self, loop_info: Dict[str, Any], original_instruct conversation_manager.add_message("user", message) """ # Import here to avoid circular imports - from core.prompts import prompts + from core.metacognition.prompts import prompts return prompts.format_loop_breaking_message( loop_type=loop_info['type'], diff --git a/SimpleAgent/core/metacognition/metacognition.py b/SimpleAgent/core/metacognition/metacognition.py new file mode 100644 index 0000000..ee5662f --- /dev/null +++ b/SimpleAgent/core/metacognition/metacognition.py @@ -0,0 +1,227 @@ +""" +Metacognition Module + +This module provides the agent with internal monologue +capabilities to intelligently understand task progress and completion. +The agent can reflect on its own actions and reasoning to make smart decisions. +""" + +import json +import time +from typing import List, Dict, Any, Optional, Tuple +from dataclasses import dataclass + +from core.metacognition.prompts import prompts +from core.utils.config import METACOGNITION_MODEL + + +@dataclass +class TaskGoal: + """Represents what the agent is trying to accomplish""" + primary_objective: str + success_criteria: List[str] + estimated_complexity: str # 'simple', 'moderate', 'complex' + requires_tools: bool + expected_deliverables: List[str] + + +@dataclass +class ActionReflection: + """Represents the agent's reflection on an action it took""" + step_number: int + action_taken: str + tools_used: List[str] + outcome_achieved: str + progress_made: str + remaining_work: str + confidence_level: float # 0.0 to 1.0 + + +class MetaCognition: + """ + Provides the agent with internal monologue and self-awareness capabilities. + The agent can think about its own progress and make intelligent decisions. + """ + + def __init__(self, model_client): + self.model_client = model_client + self.current_goal: Optional[TaskGoal] = None + self.action_reflections: List[ActionReflection] = [] + self.internal_thoughts: List[str] = [] + self.task_started_at = None + + def analyze_user_instruction(self, instruction: str) -> TaskGoal: + """ + Have the agent think deeply about what the user is asking for + and what success would look like. + """ + analysis_prompt = prompts.format_task_analysis(instruction) + + try: + response = self.model_client.chat.completions.create( + model=METACOGNITION_MODEL, + messages=[{"role": "user", "content": analysis_prompt}], + temperature=0.1 + ) + + analysis = json.loads(response.choices[0].message.content) + + self.current_goal = TaskGoal( + primary_objective=analysis["primary_objective"], + success_criteria=analysis["success_criteria"], + estimated_complexity=analysis["estimated_complexity"], + requires_tools=analysis["requires_tools"], + expected_deliverables=analysis["expected_deliverables"] + ) + + self.internal_thoughts.append(f"TASK ANALYSIS: {analysis['reasoning']}") + self.task_started_at = time.time() + + return self.current_goal + + except Exception as e: + # Fallback if analysis fails + self.current_goal = TaskGoal( + primary_objective=instruction, + success_criteria=["Complete the requested task"], + estimated_complexity="moderate", + requires_tools=True, + expected_deliverables=["Task completion"] + ) + return self.current_goal + + def reflect_on_action(self, step_number: int, assistant_response: str, + tools_used: List[str], tool_results: List[str]) -> ActionReflection: + """ + Have the agent reflect on what it just did and assess progress. + """ + if not self.current_goal: + return None + + reflection_prompt = prompts.format_action_reflection( + primary_objective=self.current_goal.primary_objective, + success_criteria=', '.join(self.current_goal.success_criteria), + expected_deliverables=', '.join(self.current_goal.expected_deliverables), + step_number=step_number, + assistant_response=assistant_response, + tools_used=', '.join(tools_used) if tools_used else 'None', + tool_results=str(tool_results) if tool_results else 'None' + ) + + try: + response = self.model_client.chat.completions.create( + model=METACOGNITION_MODEL, + messages=[{"role": "user", "content": reflection_prompt}], + temperature=0.2 + ) + + reflection_data = json.loads(response.choices[0].message.content) + + reflection = ActionReflection( + step_number=step_number, + action_taken=assistant_response, + tools_used=tools_used, + outcome_achieved=reflection_data["outcome_achieved"], + progress_made=reflection_data["progress_made"], + remaining_work=reflection_data["remaining_work"], + confidence_level=float(reflection_data["confidence_level"]) + ) + + self.action_reflections.append(reflection) + self.internal_thoughts.append(f"STEP {step_number} REFLECTION: {reflection_data['internal_thoughts']}") + + return reflection + + except Exception as e: + # Fallback reflection + return ActionReflection( + step_number=step_number, + action_taken=assistant_response, + tools_used=tools_used, + outcome_achieved="Action completed", + progress_made="Made progress", + remaining_work="Continuing task", + confidence_level=0.5 + ) + + def should_task_continue(self, current_step: int, max_steps: int) -> Tuple[bool, str, float]: + """ + Intelligently determine if the task should continue based on deep understanding. + + Returns: + (should_continue, reasoning, confidence) + """ + if not self.current_goal or not self.action_reflections: + return True, "Task just started, continuing", 0.5 + + # Build progress summary + progress_summary = "" + for reflection in self.action_reflections[-3:]: # Last 3 steps + progress_summary += f""" +Step {reflection.step_number}: +- Action: {reflection.action_taken[:100]}... +- Outcome: {reflection.outcome_achieved} +- Progress: {reflection.progress_made} +- Remaining: {reflection.remaining_work} +- Confidence: {reflection.confidence_level} +""" + + decision_prompt = prompts.format_continuation_decision( + primary_objective=self.current_goal.primary_objective, + success_criteria=', '.join(self.current_goal.success_criteria), + expected_deliverables=', '.join(self.current_goal.expected_deliverables), + estimated_complexity=self.current_goal.estimated_complexity, + steps_completed=len(self.action_reflections), + progress_summary=progress_summary, + current_step=current_step, + max_steps=max_steps, + time_elapsed=time.time() - self.task_started_at, + recent_thoughts=str(self.internal_thoughts[-2:] if len(self.internal_thoughts) >= 2 else self.internal_thoughts) + ) + + try: + response = self.model_client.chat.completions.create( + model=METACOGNITION_MODEL, + messages=[{"role": "user", "content": decision_prompt}], + temperature=0.1 + ) + + decision = json.loads(response.choices[0].message.content) + + should_continue = decision["decision"] == "CONTINUE" + reasoning = decision["reasoning"] + confidence = float(decision["confidence"]) + + # Add to internal thoughts + self.internal_thoughts.append(f"CONTINUATION DECISION: {decision['decision']} - {reasoning}") + + return should_continue, reasoning, confidence + + except Exception as e: + # Fallback to conservative continuation + return True, f"Error in decision making: {str(e)}", 0.3 + + def get_internal_monologue(self) -> List[str]: + """Return the agent's internal thoughts for debugging/transparency""" + return self.internal_thoughts.copy() + + def get_progress_summary(self) -> Dict[str, Any]: + """Get a summary of task progress""" + if not self.current_goal: + return {"status": "No active task"} + + return { + "goal": self.current_goal.primary_objective, + "steps_completed": len(self.action_reflections), + "average_confidence": sum(r.confidence_level for r in self.action_reflections) / len(self.action_reflections) if self.action_reflections else 0, + "recent_progress": self.action_reflections[-1].progress_made if self.action_reflections else "No progress yet", + "remaining_work": self.action_reflections[-1].remaining_work if self.action_reflections else "Unknown", + "time_elapsed": time.time() - self.task_started_at if self.task_started_at else 0 + } + + def reset(self): + """Reset the metacognition state for a new task""" + self.current_goal = None + self.action_reflections.clear() + self.internal_thoughts.clear() + self.task_started_at = None \ No newline at end of file diff --git a/SimpleAgent/core/metacognition/prompts.py b/SimpleAgent/core/metacognition/prompts.py new file mode 100644 index 0000000..ac3fcb6 --- /dev/null +++ b/SimpleAgent/core/metacognition/prompts.py @@ -0,0 +1,331 @@ +""" +Centralized Prompt Management System + +This file contains all system prompts used throughout SimpleAgent. +Having all prompts in one place makes them easy to maintain, edit, and optimize. +""" + +from typing import Dict, Any + + +class PromptTemplates: + """ + Centralized collection of all prompts used in the SimpleAgent system. + Each prompt is a template that can be formatted with specific variables. + """ + + # ============================================================================ + # MAIN AGENT SYSTEM PROMPTS + # ============================================================================ + + MAIN_AGENT_SYSTEM = """You are an AI agent with internal self-awareness and metacognitive capabilities. + +You have analyzed your current task and understand: +- Primary Objective: {primary_objective} +- Success Criteria: {success_criteria} +- Expected Deliverables: {expected_deliverables} + +Your metacognitive system will help you: +1. Understand when your objective is truly accomplished +2. Reflect on your progress after each action +3. Make intelligent decisions about when to continue or stop +4. Maintain awareness of what you've accomplished and what remains + +Current date and time: {current_datetime} +Your knowledge cutoff might be earlier, but you should consider the current date when processing tasks. +Always work with the understanding that it is now {current_year} when handling time-sensitive information. + +Focus on accomplishing your PRIMARY OBJECTIVE efficiently and intelligently. +Your metacognitive system will determine when the task is complete based on understanding, not keywords. + +{auto_mode_guidance} + +Current execution context: +- You are on step {current_step} of {max_steps} total steps +- Auto-continue is {auto_status}""" + + # ============================================================================ + # AUTO-CONTINUE MODE GUIDANCE + # ============================================================================ + + AUTO_MODE_INFINITE = """IMPORTANT: You are running in AUTO-CONTINUE mode with infinite steps. +Your metacognitive system will determine when to stop based on intelligent task analysis. +Focus on accomplishing your objective efficiently without unnecessary repetition.""" + + AUTO_MODE_LIMITED = """IMPORTANT: You are running in AUTO-CONTINUE mode. +Your metacognitive system will determine when to stop based on intelligent task analysis. +Focus on accomplishing your objective efficiently within the remaining steps.""" + + MANUAL_MODE = """You are running in MANUAL mode. +Your metacognitive system will help you understand when the task is complete. +Be clear about your progress and next steps.""" + + # ============================================================================ + # METACOGNITIVE PROMPTS + # ============================================================================ + + TASK_ANALYSIS = """You are an AI agent analyzing a user instruction to understand what needs to be accomplished. + +User Instruction: "{instruction}" + +Think carefully about this instruction and analyze: +1. What is the PRIMARY OBJECTIVE the user wants accomplished? +2. What would SUCCESS look like? What specific criteria would indicate the task is complete? +3. How complex is this task? (simple/moderate/complex) +4. Does this require using tools/commands or just conversation? +5. What specific deliverables or outcomes should be produced? + +Respond in JSON format: +{{ + "primary_objective": "Clear statement of what needs to be accomplished", + "success_criteria": ["Specific criterion 1", "Specific criterion 2", ...], + "estimated_complexity": "simple|moderate|complex", + "requires_tools": true/false, + "expected_deliverables": ["Deliverable 1", "Deliverable 2", ...], + "reasoning": "Your internal reasoning about this task" +}} + +Be specific and thoughtful. Think about what the user REALLY wants, not just the surface-level request.""" + + ACTION_REFLECTION = """You are an AI agent reflecting on an action you just took. Think carefully about your progress. + +CURRENT TASK GOAL: +Primary Objective: {primary_objective} +Success Criteria: {success_criteria} +Expected Deliverables: {expected_deliverables} + +WHAT YOU JUST DID (Step {step_number}): +Response: {assistant_response} +Tools Used: {tools_used} +Tool Results: {tool_results} + +REFLECTION QUESTIONS: +1. What specific outcome did this action achieve? +2. How much progress did this make toward the primary objective? +3. What work still remains to be done? +4. How confident are you that you're on the right track? (0.0 to 1.0) + +Respond in JSON format: +{{ + "outcome_achieved": "Specific description of what this action accomplished", + "progress_made": "How this moved you closer to the goal", + "remaining_work": "What still needs to be done to complete the task", + "confidence_level": 0.0-1.0, + "internal_thoughts": "Your honest assessment of the current situation" +}} + +Be brutally honest about progress and remaining work.""" + + CONTINUATION_DECISION = """You are an AI agent making a critical decision about whether to continue working on a task. + +ORIGINAL TASK: +Objective: {primary_objective} +Success Criteria: {success_criteria} +Expected Deliverables: {expected_deliverables} +Estimated Complexity: {estimated_complexity} + +PROGRESS SO FAR ({steps_completed} steps completed): +{progress_summary} + +CURRENT SITUATION: +- Current Step: {current_step} of {max_steps} +- Time Elapsed: {time_elapsed:.1f} seconds +- Recent Internal Thoughts: {recent_thoughts} + +DECISION CRITERIA: +1. Are the success criteria met? +2. Have the expected deliverables been produced? +3. Is the primary objective accomplished? +4. Is continued work likely to add value? +5. Are we stuck or making meaningful progress? + +Make a decision: Should the task CONTINUE or STOP? + +Respond in JSON format: +{{ + "decision": "CONTINUE" or "STOP", + "reasoning": "Detailed explanation of your decision", + "confidence": 0.0-1.0, + "completion_assessment": "Honest assessment of how complete the task is", + "next_recommended_action": "If continuing, what should be done next" +}} + +Think deeply about whether the user's original request has been genuinely fulfilled.""" + + # ============================================================================ + # LOOP DETECTION PROMPTS + # ============================================================================ + + LOOP_BREAKING_MESSAGE = """🚨 LOOP DETECTION ALERT 🚨 + +You are stuck in a {loop_type} loop (Severity: {severity}). +You have repeated similar responses {count} times across steps: {steps} + +ORIGINAL INSTRUCTION: "{original_instruction}" + +🤔 CRITICAL DECISION POINT: +You need to make a decision about how to proceed. You have TWO OPTIONS: + +OPTION 1: STOP EXECUTION (Recommended if instruction is unclear/impossible) +- If the original instruction is too vague, unclear, or seems like a placeholder +- If you genuinely cannot determine what action to take +- If the task appears to be impossible or nonsensical +- If you believe stopping would be more helpful than continuing aimlessly + +OPTION 2: TAKE CONCRETE ACTION (Recommended if you can make reasonable assumptions) +- If you can make reasonable assumptions about what the user wants +- If you can demonstrate useful capabilities even with unclear instructions +- If you can break down the vague instruction into actionable steps + +💡 TO HELP YOU DECIDE: +- Is "{original_instruction}" a clear, actionable request? +- Can you reasonably infer what the user wants you to accomplish? +- Would taking action be more helpful than stopping? + +🎯 IF YOU CHOOSE OPTION 1 (STOP): +Simply respond with a message containing the phrase "task complete" or "stopping execution" and explain why you believe stopping is the best choice given the unclear instruction. + +🎯 IF YOU CHOOSE OPTION 2 (TAKE ACTION): +Execute ONE specific tool call immediately. Here are concrete suggestions: +{action_suggestions} + +⚡ IMPORTANT RULES: +- Make your decision quickly and definitively +- NO more questions like "could you clarify", "please specify", or "what would you like" +- If you stop, explain your reasoning clearly +- If you continue, take concrete action with tools immediately + +🧠 ASK YOURSELF: +"Given the instruction '{original_instruction}', is it better to stop and explain why this instruction is unclear, or can I make reasonable assumptions and proceed with useful actions?" + +CHOOSE YOUR OPTION AND ACT NOW!""" + + # ============================================================================ + # LOOP DETECTION ACTION SUGGESTIONS + # ============================================================================ + + LOOP_SUGGESTIONS = { + 'exact_repetition': """ +- Use write_file to create a capabilities demonstration file +- Use web_search to find current information on a relevant topic +- Use list_directory to explore and work with available files""", + + 'semantic_repetition': """ +- Use web_search to gather information instead of asking questions +- Use write_file to create something useful based on reasonable assumptions +- Use any data analysis tools to demonstrate capabilities""", + + 'no_action_confusion_with_recent_actions': """ +- Build upon the actions you already took +- Extend or analyze what you previously created +- Complete the work you started rather than asking for more direction""", + + 'no_action_confusion_without_recent_actions': """ +- Use list_directory to explore available files and work with them +- Use write_file to create a useful demonstration +- Use web_search to find relevant information""" + } + + # ============================================================================ + # DATE/TIME RELATED PROMPTS + # ============================================================================ + + DATE_REMINDER = "Remember that today's date is {current_datetime} as you work on this task. All date-related calculations should use this as a reference point." + + DATE_CORRECTION = "Important correction: Today's date is {current_datetime}. Please use {current_year} as the current year for this task, not older years from your training data." + + # ============================================================================ + # USER INTERACTION PROMPTS + # ============================================================================ + + AUTO_CONTINUE_ENCOURAGEMENT = "Please continue with the next step of the task. Remember to use the available commands to make progress." + + # ============================================================================ + # UTILITY METHODS + # ============================================================================ + + @classmethod + def get_auto_mode_guidance(cls, auto_steps_remaining: int) -> str: + """Get the appropriate auto-mode guidance based on remaining steps.""" + if auto_steps_remaining == -1: + return cls.AUTO_MODE_INFINITE + elif auto_steps_remaining > 0: + return cls.AUTO_MODE_LIMITED + else: + return cls.MANUAL_MODE + + @classmethod + def format_task_analysis(cls, instruction: str) -> str: + """Format the task analysis prompt.""" + return cls.TASK_ANALYSIS.format(instruction=instruction) + + @classmethod + def format_action_reflection(cls, primary_objective: str, success_criteria: str, + expected_deliverables: str, step_number: int, + assistant_response: str, tools_used: str, tool_results: str) -> str: + """Format the action reflection prompt.""" + return cls.ACTION_REFLECTION.format( + primary_objective=primary_objective, + success_criteria=success_criteria, + expected_deliverables=expected_deliverables, + step_number=step_number, + assistant_response=assistant_response, + tools_used=tools_used, + tool_results=tool_results + ) + + @classmethod + def format_continuation_decision(cls, primary_objective: str, success_criteria: str, + expected_deliverables: str, estimated_complexity: str, + steps_completed: int, progress_summary: str, + current_step: int, max_steps: int, time_elapsed: float, + recent_thoughts: str) -> str: + """Format the continuation decision prompt.""" + return cls.CONTINUATION_DECISION.format( + primary_objective=primary_objective, + success_criteria=success_criteria, + expected_deliverables=expected_deliverables, + estimated_complexity=estimated_complexity, + steps_completed=steps_completed, + progress_summary=progress_summary, + current_step=current_step, + max_steps=max_steps, + time_elapsed=time_elapsed, + recent_thoughts=recent_thoughts + ) + + @classmethod + def format_loop_breaking_message(cls, loop_type: str, severity: str, count: int, + steps: list, original_instruction: str, + had_recent_actions: bool = False) -> str: + """Format the loop breaking message.""" + # Determine action suggestions based on loop type and context + if loop_type == 'exact_repetition': + suggestions = cls.LOOP_SUGGESTIONS['exact_repetition'] + elif loop_type == 'semantic_repetition': + suggestions = cls.LOOP_SUGGESTIONS['semantic_repetition'] + elif loop_type == 'no_action_confusion': + if had_recent_actions: + suggestions = cls.LOOP_SUGGESTIONS['no_action_confusion_with_recent_actions'] + else: + suggestions = cls.LOOP_SUGGESTIONS['no_action_confusion_without_recent_actions'] + else: + suggestions = cls.LOOP_SUGGESTIONS['no_action_confusion_without_recent_actions'] + + return cls.LOOP_BREAKING_MESSAGE.format( + loop_type=loop_type, + severity=severity, + count=count, + steps=steps, + original_instruction=original_instruction, + action_suggestions=suggestions + ) + + @classmethod + def format_main_system_prompt(cls, **kwargs) -> str: + """Format the main agent system prompt with all necessary variables.""" + return cls.MAIN_AGENT_SYSTEM.format(**kwargs) + + +# Convenience instance for easy importing +prompts = PromptTemplates() \ No newline at end of file diff --git a/SimpleAgent/core/utils/__init__.py b/SimpleAgent/core/utils/__init__.py new file mode 100644 index 0000000..0519ecb --- /dev/null +++ b/SimpleAgent/core/utils/__init__.py @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SimpleAgent/core/utils/config.py b/SimpleAgent/core/utils/config.py new file mode 100644 index 0000000..e5ba67d --- /dev/null +++ b/SimpleAgent/core/utils/config.py @@ -0,0 +1,74 @@ +""" +Configuration Module + +This module provides configuration settings for the SimpleAgent system. +""" + +import os +from dotenv import load_dotenv +from openai import OpenAI + +# Load environment variables from .env file +load_dotenv() + +# API Provider settings +API_PROVIDER = os.getenv("API_PROVIDER", "openai").lower() # "openai", "lmstudio", or "gemini" +API_BASE_URL = os.getenv("API_BASE_URL", None) # For LM-Studio: http://192.168.0.2:1234/v1 +OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") +GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") + +# GitHub settings +GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") + +# Model settings - Optimized for performance and cost +DEFAULT_MODEL = os.getenv("DEFAULT_MODEL", "gpt-4o") # Main agent (fast + powerful) +METACOGNITION_MODEL = os.getenv("METACOGNITION_MODEL", "gpt-4") # Reflection/analysis (thoughtful) +SUMMARIZER_MODEL = os.getenv("SUMMARIZER_MODEL", "gpt-3.5-turbo") # Summaries (fast + cheap) + +# For LM-Studio, we might want to use the same model for both +if API_PROVIDER == "lmstudio": + # Override models if LM-Studio specific models are set + DEFAULT_MODEL = os.getenv("DEFAULT_MODEL", "deepseek-r1-distill-llama-8b") + METACOGNITION_MODEL = os.getenv("METACOGNITION_MODEL", "deepseek-r1-distill-llama-8b") + SUMMARIZER_MODEL = os.getenv("SUMMARIZER_MODEL", "deepseek-r1-distill-llama-8b") + +# Output directory - All file operations MUST happen within this directory +# Can be customized through environment variable +OUTPUT_DIR = os.getenv("OUTPUT_DIR", "output") +if not os.path.exists(OUTPUT_DIR): + os.makedirs(OUTPUT_DIR) + +# Memory settings +MEMORY_FILE = os.path.join(OUTPUT_DIR, os.getenv("MEMORY_FILE", "memory.json")) + +# Application settings +MAX_STEPS = int(os.getenv("MAX_STEPS", "10")) +DEBUG_MODE = os.getenv("DEBUG_MODE", "False").lower() == "true" + + +def create_client(): + """ + Create an API client based on the configured API provider. + Returns: + API client for OpenAI, LM-Studio, or Gemini + """ + if API_PROVIDER == "lmstudio": + if not API_BASE_URL: + raise ValueError("API_BASE_URL must be set when using LM-Studio provider") + from openai import OpenAI + api_key = OPENAI_API_KEY or "lm-studio-local" + return OpenAI( + base_url=API_BASE_URL, + api_key=api_key + ) + elif API_PROVIDER == "gemini": + if not GEMINI_API_KEY: + raise ValueError("GEMINI_API_KEY must be set when using Gemini provider") + from google import genai + return genai.Client(api_key=GEMINI_API_KEY) + else: + # Default to OpenAI + if not OPENAI_API_KEY: + raise ValueError("OPENAI_API_KEY must be set when using OpenAI provider") + from openai import OpenAI + return OpenAI(api_key=OPENAI_API_KEY) \ No newline at end of file diff --git a/SimpleAgent/core/security.py b/SimpleAgent/core/utils/security.py similarity index 98% rename from SimpleAgent/core/security.py rename to SimpleAgent/core/utils/security.py index 84a925a..fa99d98 100644 --- a/SimpleAgent/core/security.py +++ b/SimpleAgent/core/utils/security.py @@ -11,7 +11,7 @@ """ import os -from core.config import OUTPUT_DIR +from core.utils.config import OUTPUT_DIR def get_secure_path(file_path: str, base_dir: str = OUTPUT_DIR) -> str: """ diff --git a/SimpleAgent/core/version.py b/SimpleAgent/core/utils/version.py similarity index 100% rename from SimpleAgent/core/version.py rename to SimpleAgent/core/utils/version.py diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..ab68a10 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,19 @@ +# Simple Agent Documentation + +This folder contains the full documentation for the Simple Agent system. + +## How to Use +- Browse the markdown files directly in `docs/` for detailed information on every part of the system. +- Start with [index.md](index.md) for an overview and table of contents. + +## Extending the Docs +- Add new `.md` files for new modules, features, or guides. +- Update the table of contents in `index.md` as needed. + +## Static Site Generation +- The docs are compatible with [MkDocs](https://www.mkdocs.org/), [Docusaurus](https://docusaurus.io/), and similar tools. +- To build a static site, add a `mkdocs.yml` or equivalent config and run the appropriate build command. + +## Contributing +- Please keep documentation up to date with code changes. +- PRs improving docs are always welcome! \ No newline at end of file diff --git a/docs/api_reference.md b/docs/api_reference.md new file mode 100644 index 0000000..0bec426 --- /dev/null +++ b/docs/api_reference.md @@ -0,0 +1,8 @@ +# API Reference + +This section will contain detailed documentation for all public classes, functions, and APIs in Simple Agent. + +- Each core class and function will be described with its parameters, return values, and usage examples. +- For now, see the individual module docs for high-level overviews. + +(Coming soon: auto-generated API docs!) \ No newline at end of file diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..3b3d103 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,40 @@ +# Architecture Overview + +``` ++-------------------+ +| SimpleAgent.py | ++-------------------+ + | + v ++-------------------+ +| core/ | ++-------------------+ +| agent/ | +| execution/ | +| conversation/ | +| metacognition/ | +| utils/ | ++-------------------+ + | + v ++-------------------+ +| commands/ | ++-------------------+ +``` + +## Main Components +- **SimpleAgent.py**: Entry point and CLI interface. +- **core/**: Main framework logic, split into submodules: + - **agent/**: Main agent class and run loop manager. + - **execution/**: Command execution, tool management, summarization. + - **conversation/**: Conversation and memory management. + - **metacognition/**: Self-reflection, loop detection, prompt templates. + - **utils/**: Security, configuration, versioning. +- **commands/**: Pluggable tools and commands, loaded dynamically. + +## How It Works +1. User provides an instruction via CLI. +2. The agent orchestrates conversation, tool use, and memory. +3. Tools are loaded on demand from local or remote sources. +4. All file operations are sandboxed and secure. +5. The agent uses metacognition to reflect, summarize, and avoid loops. \ No newline at end of file diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..5ea8ca3 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,14 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [Unreleased] +- ... + +## [v0.8.2] - YYYY-MM-DD +- Major refactor: modularized core/ into subfolders +- Improved documentation and project structure +- Enhanced security and tool management + +## [Older Versions] +- See GitHub Releases for previous changelogs \ No newline at end of file diff --git a/docs/commands.md b/docs/commands.md new file mode 100644 index 0000000..9efd033 --- /dev/null +++ b/docs/commands.md @@ -0,0 +1,65 @@ +# Commands System + +## Overview +Simple Agent supports a dynamic, extensible command system. Tools (commands) can be loaded from both local and remote sources, and are used to perform actions such as file operations, web requests, data analysis, and more. + +## How Commands Work (Step by Step) + +1. **Discovery**: On startup, the agent scans the local `commands/` directory and fetches the remote tool catalog. +2. **On-Demand Loading**: When the agent needs a tool, it loads it from local or remote sources as needed. +3. **Schema Validation**: Each tool defines a schema for its parameters, ensuring correct usage. +4. **Execution**: The tool is called with the required arguments, and the result is returned to the agent. +5. **Tracking**: All tool usage is tracked for memory and summarization. + +--- + +### Example: Using a Tool +- The agent needs to write a file, so it loads the `write_file` tool. +- The tool is executed with the file path and content. +- The result is logged and added to memory. + +--- + +### In Plain English +- The commands system is like a toolbox: the agent grabs the right tool for the job, uses it safely, and always keeps track of what it did. + +## Adding Your Own Command +1. Create a new directory under `commands/` for your category (if needed). +2. Add a subdirectory for your tool, with an `__init__.py` file. +3. Register your command using the `register_command` function from the tool manager. +4. Define a schema for your command's parameters. +5. (Optional) Contribute your tool to the main tools repo! + +## Example Command Structure +``` +commands/ + file_ops/ + write_file/ + __init__.py +``` + +## Example Command Registration +```python +from core.execution.tool_manager import register_command + +def write_file(file_path: str, content: str): + with open(file_path, 'w') as f: + f.write(content) + return f"Wrote to {file_path}" + +WRITE_FILE_SCHEMA = { + "function": { + "name": "write_file", + "parameters": { + "type": "object", + "properties": { + "file_path": {"type": "string"}, + "content": {"type": "string"} + }, + "required": ["file_path", "content"] + } + } +} + +register_command("write_file", write_file, WRITE_FILE_SCHEMA) +``` \ No newline at end of file diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..ec1b68a --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,49 @@ +# Configuration + +Simple Agent is configured via environment variables in the `.env` file. + +## Main Options +- `API_PROVIDER`: `openai`, `lmstudio`, or `gemini` +- `OPENAI_API_KEY`: Your OpenAI API key +- `GEMINI_API_KEY`: Your Google Gemini API key +- `API_BASE_URL`: LM-Studio endpoint (if using LM-Studio) +- `GITHUB_TOKEN`: GitHub token for tool loading (optional) +- `DEFAULT_MODEL`: Main model for agent operations +- `SUMMARIZER_MODEL`: Model for summarization +- `METACOGNITION_MODEL`: Model for metacognitive reflection +- `MAX_STEPS`: Maximum steps per run +- `DEBUG_MODE`: Enable debug logging +- `OUTPUT_DIR`: Directory for file operations +- `MEMORY_FILE`: File for persistent memory + +## Example: OpenAI +```env +API_PROVIDER=openai +OPENAI_API_KEY=your_openai_api_key_here +GITHUB_TOKEN=your_github_token_here +DEFAULT_MODEL=gpt-4o +SUMMARIZER_MODEL=gpt-3.5-turbo +MAX_STEPS=10 +DEBUG_MODE=False +OUTPUT_DIR=output +``` + +## Example: LM-Studio +```env +API_PROVIDER=lmstudio +API_BASE_URL=http://localhost:1234/v1 +DEFAULT_MODEL=deepseek-r1-distill-llama-8b +SUMMARIZER_MODEL=deepseek-r1-distill-llama-8b +MAX_STEPS=10 +DEBUG_MODE=False +``` + +## Example: Gemini +```env +API_PROVIDER=gemini +GEMINI_API_KEY=your_gemini_api_key_here +DEFAULT_MODEL=gemini-2.0-flash +SUMMARIZER_MODEL=gemini-2.0-flash +MAX_STEPS=10 +DEBUG_MODE=False +``` \ No newline at end of file diff --git a/docs/core/agent.md b/docs/core/agent.md new file mode 100644 index 0000000..f46d5d8 --- /dev/null +++ b/docs/core/agent.md @@ -0,0 +1,72 @@ +# core/agent/ + +## Overview +The `agent/` submodule contains the main agent interface and the run loop manager. + +### Files +- **agent.py**: Defines the `SimpleAgent` class, the main entry point for using the agent. It coordinates conversation, execution, memory, and security. +- **run_manager.py**: Implements the `RunManager` class, which manages the main execution loop, orchestrating conversation, tool use, memory, and metacognition. + +### Key Classes +- **SimpleAgent**: High-level interface for running the agent, managing state, and exposing core functionality. +- **RunManager**: Handles the step-by-step execution of tasks, including metacognitive analysis, loop detection, and summarization. + +### Responsibilities +- Orchestrate the agent's workflow +- Manage conversation and memory +- Coordinate tool execution and metacognitive reasoning +- Provide a secure, extensible interface for automation tasks + +## How the Agent Works (Step by Step) + +1. **User Input** + - The user runs `python SimpleAgent.py "Do something"`. + - The agent receives the instruction. +2. **Initialization** + - Loads configuration and environment variables. + - Sets up memory, conversation, and tool management. +3. **Task Analysis (Metacognition)** + - The agent analyzes the instruction to determine the main goal and success criteria. +4. **Main Run Loop** + - For each step: + - Updates the system prompt with the current objective and context. + - Asks the model what to do next. + - Executes any tool calls securely. + - Updates memory and conversation history. + - Reflects on progress and checks for loops. + - Decides whether to continue or stop. +5. **Finalization** + - Summarizes changes and progress. + - Saves the final state to memory. + - Prints a summary and exits. + +### Example: Creating a Flask API + +```bash +python SimpleAgent.py -a 10 "Create a Python Flask API with time endpoints" +``` +- The agent analyzes the instruction, plans the steps, and uses tools to write code files. +- It checks its own progress after each step, ensuring it's on track. +- If it gets stuck, it detects the loop and tries a new approach or stops. + +### Diagram + +``` +User Input + | + v +SimpleAgent (agent.py) + | + v +RunManager (run_manager.py) + | + v +[Conversation | Execution | Memory | Metacognition] + | + v +Tools/Commands +``` + +### In Plain English +- The agent is like a smart assistant that plans, acts, checks its own work, and learns from each step. +- It keeps everything secure and organized, and always knows when to stop or try something new. \ No newline at end of file diff --git a/docs/core/conversation.md b/docs/core/conversation.md new file mode 100644 index 0000000..4c71869 --- /dev/null +++ b/docs/core/conversation.md @@ -0,0 +1,37 @@ +# core/conversation/ + +## Overview +The `conversation/` submodule manages conversation history and persistent memory. + +### Files +- **conversation.py**: Contains the `ConversationManager` class for managing the conversation history and message flow. +- **memory.py**: Implements the `MemoryManager` class for saving, loading, and updating persistent memory (conversations, files created/modified). + +### Key Classes +- **ConversationManager**: Handles the conversation history, message addition, and system message updates. +- **MemoryManager**: Manages persistent memory, including conversations and file tracking. + +--- + +## How Conversation & Memory Work + +1. **Every message** (user, agent, tool) is added to the conversation history. +2. **System messages** are updated to keep the agent on track. +3. **MemoryManager** saves conversations and file changes to disk. +4. **On startup**, memory is loaded so the agent can pick up where it left off. + +--- + +### Example: Remembering a File +- The agent creates a file. The path is added to memory. +- On the next run, the agent can see what files it created or modified before. + +--- + +### In Plain English +- This part of the agent is like a notebook: it remembers every conversation and every file it touches, so it never loses track of what it's done. + +### Responsibilities +- Track and manage all agent conversations +- Persist memory across runs +- Support context-aware and stateful agent behavior \ No newline at end of file diff --git a/docs/core/execution.md b/docs/core/execution.md new file mode 100644 index 0000000..63c7f64 --- /dev/null +++ b/docs/core/execution.md @@ -0,0 +1,38 @@ +# core/execution/ + +## Overview +The `execution/` submodule handles command execution, tool management, and summarization. + +### Files +- **execution.py**: Contains the `ExecutionManager` class, which manages command execution, step management, and file operation security. +- **tool_manager.py**: Implements the `ToolManager` class and related functions for dynamic tool discovery, loading, and registration. +- **summarizer.py**: Provides the `ChangeSummarizer` class for summarizing changes made by the agent. + +### Key Classes +- **ExecutionManager**: Executes commands, manages tool calls, and enforces file operation security. +- **ToolManager**: Discovers, loads, and registers tools from local and remote sources. +- **ChangeSummarizer**: Summarizes changes for step-by-step and overall reporting. + +### Responsibilities +- Execute agent actions and tool calls +- Manage dynamic tool/plugin loading +- Summarize changes and progress +- Enforce security for all file operations + +## How Execution Works + +1. **Receives an action** from the agent (e.g., "write a file"). +2. **Validates and secures** all file paths and arguments. +3. **Loads the required tool** (from local or remote) if not already loaded. +4. **Executes the tool function** with the given arguments. +5. **Tracks changes** for summarization and memory. +6. **Returns results** to the agent for further processing. + +### Example: Writing a File + +- The agent decides to call the `write_file` tool. +- `ExecutionManager` ensures the file path is safe, loads the tool, and runs it. +- The result (e.g., "Wrote to output/app.py") is tracked and summarized. + +### In Plain English +- This part of the agent is like a secure, smart robot arm: it only does safe actions, loads the right tool for the job, and keeps a log of everything it changes. \ No newline at end of file diff --git a/docs/core/index.md b/docs/core/index.md new file mode 100644 index 0000000..f636805 --- /dev/null +++ b/docs/core/index.md @@ -0,0 +1,11 @@ +# Core Modules Overview + +The `core/` directory contains the main framework logic for Simple Agent, organized into submodules: + +- [agent/](agent.md): Main agent class and run loop manager +- [execution/](execution.md): Command execution, tool management, summarization +- [conversation/](conversation.md): Conversation and memory management +- [metacognition/](metacognition.md): Self-reflection, loop detection, prompt templates +- [utils/](utils.md): Security, configuration, versioning + +Each submodule is documented in its own file for clarity and maintainability. \ No newline at end of file diff --git a/docs/core/metacognition.md b/docs/core/metacognition.md new file mode 100644 index 0000000..037ad62 --- /dev/null +++ b/docs/core/metacognition.md @@ -0,0 +1,32 @@ +# core/metacognition/ + +## Overview +The `metacognition/` submodule provides self-reflection, loop detection, and prompt management for the agent. + +### Files +- **metacognition.py**: Contains the `MetaCognition` class for internal monologue, task analysis, and intelligent stopping decisions. +- **loop_detector.py**: Implements the `LoopDetector` class for detecting and breaking repetitive loops in agent behavior. +- **prompts.py**: Centralizes all prompt templates and formatting logic for system, metacognitive, and loop-breaking messages. + +### Key Classes +- **MetaCognition**: Analyzes tasks, reflects on actions, and decides when to continue or stop. +- **LoopDetector**: Detects exact and semantic repetition, confusion, and no-action loops. + +### Responsibilities +- Enable the agent to reflect on its own progress +- Detect and break out of unproductive loops +- Centralize and manage all prompt templates + +## How Metacognition Works + +1. **Task Analysis**: The agent thinks about what the user really wants and what success looks like. +2. **Action Reflection**: After each step, the agent reflects on what it just did and how much progress it made. +3. **Loop Detection**: The agent checks if it's repeating itself or getting stuck. +4. **Stopping Decision**: The agent decides if it should keep going or stop, based on progress and confidence. + +### Example: Avoiding a Loop +- The agent notices it's giving the same answer multiple times. +- It triggers a loop-breaking prompt and tries a new approach or stops. + +### In Plain English +- This part of the agent is like an inner voice: it thinks about the task, checks its own work, and knows when to stop or try something different. \ No newline at end of file diff --git a/docs/core/utils.md b/docs/core/utils.md new file mode 100644 index 0000000..09362ce --- /dev/null +++ b/docs/core/utils.md @@ -0,0 +1,35 @@ +# core/utils/ + +## Overview +The `utils/` submodule provides utility functions and configuration for the agent. + +### Files +- **security.py**: Contains secure path handling and validation logic to prevent directory traversal and enforce sandboxing. +- **config.py**: Loads and manages all configuration and environment variables for the agent. +- **version.py**: Tracks the current version and changelog notes for the project. + +### Key Functions/Classes +- **get_secure_path**: Ensures all file operations are restricted to the output directory. +- **create_client**: Instantiates the correct API client based on configuration. + +--- + +## How Utils Work + +1. **Security**: Every file path is checked and sanitized before use. +2. **Configuration**: All settings are loaded from `.env` and made available to the agent. +3. **Versioning**: The current version is tracked for debugging and changelogs. + +--- + +### Example: Securing a File Path +```python +from core.utils.security import get_secure_path +safe_path = get_secure_path("../../etc/passwd") +# Result: 'output/passwd' (blocked from escaping output dir) +``` + +--- + +### In Plain English +- This part of the agent is like a safety net and a settings panel: it keeps everything secure and makes sure the agent always knows its configuration and version. \ No newline at end of file diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..2e49a0a --- /dev/null +++ b/docs/development.md @@ -0,0 +1,43 @@ +# Development & Contributing + +## How to Contribute +1. Fork the repository and clone your fork. +2. Create a feature branch for your changes. +3. Make your changes, following the code style and structure. +4. Write or update tests as needed. +5. Commit and push your changes. +6. Open a pull request (PR) with a clear description. + +--- + +## How Development Works (Step by Step) +1. **Branching**: Always work on a new branch for each feature or fix. +2. **Coding**: Follow the modular structure—put new features in the right submodule. +3. **Testing**: Add or update tests to cover your changes. +4. **Documentation**: Update the docs so others can understand and use your work. +5. **Pull Request**: Submit your PR and respond to feedback. + +--- + +### In Plain English +- Contributing is like adding a new tool or feature to a well-organized workshop: you put it in the right place, label it clearly, and make sure everyone knows how to use it. + +## Code Style +- Use clear, descriptive names for classes, functions, and variables. +- Keep modules focused and maintainable. +- Document all public classes and functions. +- Use type hints where possible. + +## Testing +- Place tests in `test_simple_agent.py` or a dedicated `tests/` directory. +- Use standard Python testing tools (e.g., `unittest`, `pytest`). +- Ensure all tests pass before submitting a PR. + +## Adding New Features +- For new tools/commands, see [commands.md](commands.md). +- For new core features, add to the appropriate submodule in `core/`. +- Update documentation for any new features or changes. + +## Reporting Issues +- Use GitHub Issues to report bugs or request features. +- Provide as much detail as possible for reproducibility. \ No newline at end of file diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..5b1c1e6 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,29 @@ +# Simple Agent Documentation + +Welcome to the documentation for **Simple Agent**! + +Simple Agent is a modular, extensible AI agent framework designed for automation, research, and rapid prototyping. It features dynamic tool loading, secure file operations, and advanced metacognitive reasoning. + +## Features +- Modular core architecture +- Dynamic tool/plugin system +- Secure, sandboxed file operations +- Persistent memory and conversation management +- Metacognitive self-reflection and loop detection +- Easy configuration and extensibility + +## Table of Contents +- [Architecture](architecture.md) +- [Usage Guide](usage.md) +- [Configuration](configuration.md) +- [Core Modules](core/index.md) + - [Agent](core/agent.md) + - [Execution](core/execution.md) + - [Conversation](core/conversation.md) + - [Metacognition](core/metacognition.md) + - [Utils](core/utils.md) +- [Commands System](commands.md) +- [Security Model](security.md) +- [Development & Contributing](development.md) +- [API Reference](api_reference.md) +- [Changelog](changelog.md) \ No newline at end of file diff --git a/docs/security.md b/docs/security.md new file mode 100644 index 0000000..2cbb2b2 --- /dev/null +++ b/docs/security.md @@ -0,0 +1,24 @@ +# Security Model + +## Overview +Simple Agent is designed with security in mind. All file operations are sandboxed and validated to prevent unauthorized access or modification outside the designated workspace. + +## Key Features +- **Sandboxed Operations**: All file and directory operations are restricted to the configured `OUTPUT_DIR`. +- **Path Validation**: The `get_secure_path` utility ensures that all file paths are normalized and checked to prevent directory traversal attacks. +- **Session Isolation**: Each run can use a unique workspace directory for isolation. +- **Tool Security**: Tools are loaded in a controlled environment, and their file operations are also sandboxed. + +## How It Works +1. All file paths are converted to be within the output directory. +2. Any attempt to access files outside the sandbox is blocked. +3. Directory traversal patterns (e.g., `../`) are sanitized. +4. Only files and directories within the allowed workspace can be read, written, or deleted. + +## Example +```python +from core.utils.security import get_secure_path + +safe_path = get_secure_path("../../etc/passwd") +# Result: 'output/passwd' (blocked from escaping output dir) +``` \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..19f3099 --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,45 @@ +# Usage Guide + +## Installation + +1. Clone the repository: + ```bash + git clone https://github.com/reagent-systems/Simple-Agent-Core + cd Simple-Agent-Core/SimpleAgent + ``` +2. Set up a virtual environment: + ```bash + python -m venv venv + venv\Scripts\activate # Windows + # or: source venv/bin/activate # Linux/Mac + ``` +3. Install dependencies: + ```bash + pip install -r requirements.txt + ``` +4. Copy and edit the `.env` file: + ```bash + copy env_example.txt .env # Windows + # or: cp env_example.txt .env # Linux/Mac + ``` + +## Running the Agent + +```bash +python SimpleAgent.py -a 10 "Create a Python Flask API with time endpoints" +``` + +## Command-Line Options +- `-a, --auto [N]`: Auto-continue for N steps (default: 10) +- `-m, --max-steps N`: Maximum number of steps (default: 10) +- `--eager-loading`: Load all tools at startup +- `instruction`: The task instruction for the AI agent + +## Example Tasks +- Web API creation +- Data analysis +- Web scraping +- File processing +- Research and summarization + +See [commands.md](commands.md) for more examples. \ No newline at end of file