diff --git a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md index 9d944fc027..92782d32d0 100644 --- a/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md +++ b/docs/i18n/ja/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md @@ -21,8 +21,8 @@ OpenHandsがリポジトリで動作する際: ``` --- name: -type: -version: +type: +version: agent: <エージェントのタイプ (通常はCodeActAgent)> triggers: - <オプション: microagentをトリガーするキーワード。トリガーを削除すると、常に含まれるようになります> diff --git a/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md b/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md index 8da4b773da..53c3628b27 100644 --- a/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md +++ b/docs/i18n/pt-BR/docusaurus-plugin-content-docs/current/usage/prompting/microagents-overview.md @@ -21,8 +21,8 @@ Todos os microagentes usam arquivos markdown com frontmatter YAML que possuem in ``` --- name: -type: -version: +type: +version: agent: triggers: - diff --git a/frontend/src/i18n/translation.json b/frontend/src/i18n/translation.json index 60e9eb96d8..f58d16268e 100644 --- a/frontend/src/i18n/translation.json +++ b/frontend/src/i18n/translation.json @@ -4961,19 +4961,19 @@ "tr": "Gezinme tamamlandı" }, "OBSERVATION_MESSAGE$RECALL": { - "en": "MicroAgent Activated", + "en": "Microagent Activated", "ja": "マイクロエージェントが有効化されました", "zh-CN": "微代理已激活", "zh-TW": "微代理已啟動", "ko-KR": "마이크로에이전트 활성화됨", "no": "MikroAgent aktivert", - "it": "MicroAgent attivato", - "pt": "MicroAgent ativado", - "es": "MicroAgent activado", + "it": "Microagent attivato", + "pt": "Microagent ativado", + "es": "Microagent activado", "ar": "تم تنشيط الوكيل المصغر", - "fr": "MicroAgent activé", + "fr": "Microagent activé", "tr": "MikroAjan Etkinleştirildi", - "de": "MicroAgent aktiviert" + "de": "Microagent aktiviert" }, "EXPANDABLE_MESSAGE$SHOW_DETAILS": { "en": "Show details", @@ -6089,4 +6089,4 @@ "tr": "belgelendirme", "de": "Dokumentation" } -} \ No newline at end of file +} diff --git a/microagents/README.md b/microagents/README.md index a130ec582c..16abed7137 100644 --- a/microagents/README.md +++ b/microagents/README.md @@ -1,6 +1,6 @@ -# OpenHands MicroAgents +# OpenHands Microagents -MicroAgents are specialized prompts that enhance OpenHands with domain-specific knowledge and task-specific workflows. They help developers by providing expert guidance, automating common tasks, and ensuring consistent practices across projects. Each microagent is designed to excel in a specific area, from Git operations to code review processes. +Microagents are specialized prompts that enhance OpenHands with domain-specific knowledge and task-specific workflows. They help developers by providing expert guidance, automating common tasks, and ensuring consistent practices across projects. Each microagent is designed to excel in a specific area, from Git operations to code review processes. ## Sources of Microagents @@ -49,7 +49,7 @@ When OpenHands works with a repository, it: 2. Loads relevant knowledge agents based on keywords in conversations 3. Enable task agent if user select one of them -## Types of MicroAgents +## Types of Microagents Most microagents use markdown files with YAML frontmatter. For repository agents (repo.md), the frontmatter is optional - if not provided, the file will be loaded with default settings as a repository agent. diff --git a/openhands/core/exceptions.py b/openhands/core/exceptions.py index c154152d4b..4d706e6aa5 100644 --- a/openhands/core/exceptions.py +++ b/openhands/core/exceptions.py @@ -222,14 +222,14 @@ class BrowserUnavailableException(Exception): # ============================================ -class MicroAgentError(Exception): +class MicroagentError(Exception): """Base exception for all microagent errors.""" pass -class MicroAgentValidationError(MicroAgentError): +class MicroagentValidationError(MicroagentError): """Raised when there's a validation error in microagent metadata.""" - def __init__(self, message: str = 'Micro agent validation failed') -> None: + def __init__(self, message: str = 'Microagent validation failed') -> None: super().__init__(message) diff --git a/openhands/core/setup.py b/openhands/core/setup.py index 3e9de6306b..c403ae737f 100644 --- a/openhands/core/setup.py +++ b/openhands/core/setup.py @@ -18,7 +18,7 @@ from openhands.events.event import Event from openhands.integrations.provider import ProviderToken, ProviderType, SecretStore from openhands.llm.llm import LLM from openhands.memory.memory import Memory -from openhands.microagent.microagent import BaseMicroAgent +from openhands.microagent.microagent import BaseMicroagent from openhands.runtime import get_runtime_cls from openhands.runtime.base import Runtime from openhands.security import SecurityAnalyzer, options @@ -160,7 +160,7 @@ def create_memory( memory.set_runtime_info(runtime) # loads microagents from repo/.openhands/microagents - microagents: list[BaseMicroAgent] = runtime.get_microagents_from_selected_repo( + microagents: list[BaseMicroagent] = runtime.get_microagents_from_selected_repo( selected_repository ) memory.load_user_workspace_microagents(microagents) diff --git a/openhands/memory/memory.py b/openhands/memory/memory.py index 4ddf66f043..85576a1d0a 100644 --- a/openhands/memory/memory.py +++ b/openhands/memory/memory.py @@ -15,9 +15,9 @@ from openhands.events.observation.agent import ( from openhands.events.observation.empty import NullObservation from openhands.events.stream import EventStream, EventStreamSubscriber from openhands.microagent import ( - BaseMicroAgent, - KnowledgeMicroAgent, - RepoMicroAgent, + BaseMicroagent, + KnowledgeMicroagent, + RepoMicroagent, load_microagents_from_dir, ) from openhands.runtime.base import Runtime @@ -58,8 +58,8 @@ class Memory: ) # Additional placeholders to store user workspace microagents - self.repo_microagents: dict[str, RepoMicroAgent] = {} - self.knowledge_microagents: dict[str, KnowledgeMicroAgent] = {} + self.repo_microagents: dict[str, RepoMicroagent] = {} + self.knowledge_microagents: dict[str, KnowledgeMicroagent] = {} # Store repository / runtime info to send them to the templating later self.repository_info: RepositoryInfo | None = None @@ -229,7 +229,7 @@ class Memory: return recalled_content def load_user_workspace_microagents( - self, user_microagents: list[BaseMicroAgent] + self, user_microagents: list[BaseMicroagent] ) -> None: """ This method loads microagents from a user's cloned repo or workspace directory. @@ -240,9 +240,9 @@ class Memory: 'Loading user workspace microagents: %s', [m.name for m in user_microagents] ) for user_microagent in user_microagents: - if isinstance(user_microagent, KnowledgeMicroAgent): + if isinstance(user_microagent, KnowledgeMicroagent): self.knowledge_microagents[user_microagent.name] = user_microagent - elif isinstance(user_microagent, RepoMicroAgent): + elif isinstance(user_microagent, RepoMicroagent): self.repo_microagents[user_microagent.name] = user_microagent def _load_global_microagents(self) -> None: @@ -253,10 +253,10 @@ class Memory: GLOBAL_MICROAGENTS_DIR ) for name, agent in knowledge_agents.items(): - if isinstance(agent, KnowledgeMicroAgent): + if isinstance(agent, KnowledgeMicroagent): self.knowledge_microagents[name] = agent for name, agent in repo_agents.items(): - if isinstance(agent, RepoMicroAgent): + if isinstance(agent, RepoMicroagent): self.repo_microagents[name] = agent def set_repository_info(self, repo_name: str, repo_directory: str) -> None: diff --git a/openhands/microagent/__init__.py b/openhands/microagent/__init__.py index c38a5c77ab..2fa14b7627 100644 --- a/openhands/microagent/__init__.py +++ b/openhands/microagent/__init__.py @@ -1,19 +1,19 @@ from .microagent import ( - BaseMicroAgent, - KnowledgeMicroAgent, - RepoMicroAgent, - TaskMicroAgent, + BaseMicroagent, + KnowledgeMicroagent, + RepoMicroagent, + TaskMicroagent, load_microagents_from_dir, ) -from .types import MicroAgentMetadata, MicroAgentType, TaskInput +from .types import MicroagentMetadata, MicroagentType, TaskInput __all__ = [ - 'BaseMicroAgent', - 'KnowledgeMicroAgent', - 'RepoMicroAgent', - 'TaskMicroAgent', - 'MicroAgentMetadata', - 'MicroAgentType', + 'BaseMicroagent', + 'KnowledgeMicroagent', + 'RepoMicroagent', + 'TaskMicroagent', + 'MicroagentMetadata', + 'MicroagentType', 'TaskInput', 'load_microagents_from_dir', ] diff --git a/openhands/microagent/microagent.py b/openhands/microagent/microagent.py index ff846c5013..aef2e245b8 100644 --- a/openhands/microagent/microagent.py +++ b/openhands/microagent/microagent.py @@ -6,25 +6,25 @@ import frontmatter from pydantic import BaseModel from openhands.core.exceptions import ( - MicroAgentValidationError, + MicroagentValidationError, ) from openhands.core.logger import openhands_logger as logger -from openhands.microagent.types import MicroAgentMetadata, MicroAgentType +from openhands.microagent.types import MicroagentMetadata, MicroagentType -class BaseMicroAgent(BaseModel): +class BaseMicroagent(BaseModel): """Base class for all microagents.""" name: str content: str - metadata: MicroAgentMetadata + metadata: MicroagentMetadata source: str # path to the file - type: MicroAgentType + type: MicroagentType @classmethod def load( cls, path: Union[str, Path], file_content: str | None = None - ) -> 'BaseMicroAgent': + ) -> 'BaseMicroagent': """Load a microagent from a markdown file with frontmatter.""" path = Path(path) if isinstance(path, str) else path @@ -35,12 +35,12 @@ class BaseMicroAgent(BaseModel): # Legacy repo instructions are stored in .openhands_instructions if path.name == '.openhands_instructions': - return RepoMicroAgent( + return RepoMicroagent( name='repo_legacy', content=file_content, - metadata=MicroAgentMetadata(name='repo_legacy'), + metadata=MicroagentMetadata(name='repo_legacy'), source=str(path), - type=MicroAgentType.REPO_KNOWLEDGE, + type=MicroagentType.REPO_KNOWLEDGE, ) file_io = io.StringIO(file_content) @@ -51,15 +51,15 @@ class BaseMicroAgent(BaseModel): metadata_dict = loaded.metadata or {} try: - metadata = MicroAgentMetadata(**metadata_dict) + metadata = MicroagentMetadata(**metadata_dict) except Exception as e: - raise MicroAgentValidationError(f'Error loading metadata: {e}') from e + raise MicroagentValidationError(f'Error loading metadata: {e}') from e # Create appropriate subclass based on type subclass_map = { - MicroAgentType.KNOWLEDGE: KnowledgeMicroAgent, - MicroAgentType.REPO_KNOWLEDGE: RepoMicroAgent, - MicroAgentType.TASK: TaskMicroAgent, + MicroagentType.KNOWLEDGE: KnowledgeMicroagent, + MicroagentType.REPO_KNOWLEDGE: RepoMicroagent, + MicroagentType.TASK: TaskMicroagent, } if metadata.type not in subclass_map: raise ValueError(f'Unknown microagent type: {metadata.type}') @@ -74,7 +74,7 @@ class BaseMicroAgent(BaseModel): ) -class KnowledgeMicroAgent(BaseMicroAgent): +class KnowledgeMicroagent(BaseMicroagent): """Knowledge micro-agents provide specialized expertise that's triggered by keywords in conversations. They help with: - Language best practices - Framework guidelines @@ -84,8 +84,8 @@ class KnowledgeMicroAgent(BaseMicroAgent): def __init__(self, **data): super().__init__(**data) - if self.type != MicroAgentType.KNOWLEDGE: - raise ValueError('KnowledgeMicroAgent must have type KNOWLEDGE') + if self.type != MicroagentType.KNOWLEDGE: + raise ValueError('KnowledgeMicroagent must have type KNOWLEDGE') def match_trigger(self, message: str) -> str | None: """Match a trigger in the message. @@ -103,10 +103,10 @@ class KnowledgeMicroAgent(BaseMicroAgent): return self.metadata.triggers -class RepoMicroAgent(BaseMicroAgent): - """MicroAgent specialized for repository-specific knowledge and guidelines. +class RepoMicroagent(BaseMicroagent): + """Microagent specialized for repository-specific knowledge and guidelines. - RepoMicroAgents are loaded from `.openhands/microagents/repo.md` files within repositories + RepoMicroagents are loaded from `.openhands/microagents/repo.md` files within repositories and contain private, repository-specific instructions that are automatically loaded when working with that repository. They are ideal for: - Repository-specific guidelines @@ -117,23 +117,23 @@ class RepoMicroAgent(BaseMicroAgent): def __init__(self, **data): super().__init__(**data) - if self.type != MicroAgentType.REPO_KNOWLEDGE: - raise ValueError('RepoMicroAgent must have type REPO_KNOWLEDGE') + if self.type != MicroagentType.REPO_KNOWLEDGE: + raise ValueError('RepoMicroagent must have type REPO_KNOWLEDGE') -class TaskMicroAgent(BaseMicroAgent): - """MicroAgent specialized for task-based operations.""" +class TaskMicroagent(BaseMicroagent): + """Microagent specialized for task-based operations.""" def __init__(self, **data): super().__init__(**data) - if self.type != MicroAgentType.TASK: - raise ValueError('TaskMicroAgent must have type TASK') + if self.type != MicroagentType.TASK: + raise ValueError('TaskMicroagent must have type TASK') def load_microagents_from_dir( microagent_dir: Union[str, Path], ) -> tuple[ - dict[str, RepoMicroAgent], dict[str, KnowledgeMicroAgent], dict[str, TaskMicroAgent] + dict[str, RepoMicroagent], dict[str, KnowledgeMicroagent], dict[str, TaskMicroagent] ]: """Load all microagents from the given directory. @@ -161,12 +161,12 @@ def load_microagents_from_dir( if file.name == 'README.md': continue try: - agent = BaseMicroAgent.load(file) - if isinstance(agent, RepoMicroAgent): + agent = BaseMicroagent.load(file) + if isinstance(agent, RepoMicroagent): repo_agents[agent.name] = agent - elif isinstance(agent, KnowledgeMicroAgent): + elif isinstance(agent, KnowledgeMicroagent): knowledge_agents[agent.name] = agent - elif isinstance(agent, TaskMicroAgent): + elif isinstance(agent, TaskMicroagent): task_agents[agent.name] = agent logger.debug(f'Loaded agent {agent.name} from {file}') except Exception as e: diff --git a/openhands/microagent/types.py b/openhands/microagent/types.py index 63cce23ba1..8542faafa5 100644 --- a/openhands/microagent/types.py +++ b/openhands/microagent/types.py @@ -3,7 +3,7 @@ from enum import Enum from pydantic import BaseModel, Field -class MicroAgentType(str, Enum): +class MicroagentType(str, Enum): """Type of microagent.""" KNOWLEDGE = 'knowledge' @@ -11,11 +11,11 @@ class MicroAgentType(str, Enum): TASK = 'task' -class MicroAgentMetadata(BaseModel): +class MicroagentMetadata(BaseModel): """Metadata for all microagents.""" name: str = 'default' - type: MicroAgentType = Field(default=MicroAgentType.REPO_KNOWLEDGE) + type: MicroagentType = Field(default=MicroagentType.REPO_KNOWLEDGE) version: str = Field(default='1.0.0') agent: str = Field(default='CodeActAgent') triggers: list[str] = [] # optional, only exists for knowledge microagents diff --git a/openhands/runtime/base.py b/openhands/runtime/base.py index 62bfb00546..c1e19bf72a 100644 --- a/openhands/runtime/base.py +++ b/openhands/runtime/base.py @@ -50,7 +50,7 @@ from openhands.integrations.provider import ( ) from openhands.integrations.service_types import Repository from openhands.microagent import ( - BaseMicroAgent, + BaseMicroagent, load_microagents_from_dir, ) from openhands.runtime.plugins import ( @@ -414,13 +414,13 @@ class Runtime(FileEditRuntimeMixin): def get_microagents_from_selected_repo( self, selected_repository: str | None - ) -> list[BaseMicroAgent]: + ) -> list[BaseMicroagent]: """Load microagents from the selected repository. If selected_repository is None, load microagents from the current workspace. This is the main entry point for loading microagents. """ - loaded_microagents: list[BaseMicroAgent] = [] + loaded_microagents: list[BaseMicroagent] = [] workspace_root = Path(self.config.workspace_mount_path_in_sandbox) microagents_dir = workspace_root / '.openhands' / 'microagents' repo_root = None @@ -450,7 +450,7 @@ class Runtime(FileEditRuntimeMixin): if isinstance(obs, FileReadObservation): self.log('info', 'openhands_instructions microagent loaded.') loaded_microagents.append( - BaseMicroAgent.load( + BaseMicroagent.load( path='.openhands_instructions', file_content=obs.content ) ) diff --git a/openhands/server/session/agent_session.py b/openhands/server/session/agent_session.py index c7343b9d3d..0178675719 100644 --- a/openhands/server/session/agent_session.py +++ b/openhands/server/session/agent_session.py @@ -19,7 +19,7 @@ from openhands.events.stream import EventStream from openhands.integrations.provider import PROVIDER_TOKEN_TYPE, ProviderHandler from openhands.integrations.service_types import Repository from openhands.memory.memory import Memory -from openhands.microagent.microagent import BaseMicroAgent +from openhands.microagent.microagent import BaseMicroagent from openhands.runtime import get_runtime_cls from openhands.runtime.base import Runtime from openhands.runtime.impl.remote.remote_runtime import RemoteRuntime @@ -407,7 +407,7 @@ class AgentSession: memory.set_runtime_info(self.runtime) # loads microagents from repo/.openhands/microagents - microagents: list[BaseMicroAgent] = await call_sync_from_async( + microagents: list[BaseMicroagent] = await call_sync_from_async( self.runtime.get_microagents_from_selected_repo, selected_repository.full_name if selected_repository else None, ) diff --git a/tests/runtime/test_microagent.py b/tests/runtime/test_microagent.py index 0f14c2e9b8..b9e0fd02ab 100644 --- a/tests/runtime/test_microagent.py +++ b/tests/runtime/test_microagent.py @@ -7,7 +7,7 @@ from conftest import ( _load_runtime, ) -from openhands.microagent import KnowledgeMicroAgent, RepoMicroAgent, TaskMicroAgent +from openhands.microagent import KnowledgeMicroagent, RepoMicroagent, TaskMicroagent def _create_test_microagents(test_dir: str): @@ -85,10 +85,10 @@ def test_load_microagents_with_trailing_slashes( # Verify all agents are loaded knowledge_agents = [ - a for a in loaded_agents if isinstance(a, KnowledgeMicroAgent) + a for a in loaded_agents if isinstance(a, KnowledgeMicroagent) ] - repo_agents = [a for a in loaded_agents if isinstance(a, RepoMicroAgent)] - task_agents = [a for a in loaded_agents if isinstance(a, TaskMicroAgent)] + repo_agents = [a for a in loaded_agents if isinstance(a, RepoMicroagent)] + task_agents = [a for a in loaded_agents if isinstance(a, TaskMicroagent)] # Check knowledge agents assert len(knowledge_agents) == 1 @@ -128,10 +128,10 @@ def test_load_microagents_with_selected_repo(temp_dir, runtime_cls, run_as_openh # Verify all agents are loaded knowledge_agents = [ - a for a in loaded_agents if isinstance(a, KnowledgeMicroAgent) + a for a in loaded_agents if isinstance(a, KnowledgeMicroagent) ] - repo_agents = [a for a in loaded_agents if isinstance(a, RepoMicroAgent)] - task_agents = [a for a in loaded_agents if isinstance(a, TaskMicroAgent)] + repo_agents = [a for a in loaded_agents if isinstance(a, RepoMicroagent)] + task_agents = [a for a in loaded_agents if isinstance(a, TaskMicroagent)] # Check knowledge agents assert len(knowledge_agents) == 1 @@ -181,10 +181,10 @@ Repository-specific test instructions. # Verify only repo agent is loaded knowledge_agents = [ - a for a in loaded_agents if isinstance(a, KnowledgeMicroAgent) + a for a in loaded_agents if isinstance(a, KnowledgeMicroagent) ] - repo_agents = [a for a in loaded_agents if isinstance(a, RepoMicroAgent)] - task_agents = [a for a in loaded_agents if isinstance(a, TaskMicroAgent)] + repo_agents = [a for a in loaded_agents if isinstance(a, RepoMicroagent)] + task_agents = [a for a in loaded_agents if isinstance(a, TaskMicroagent)] assert len(knowledge_agents) == 0 assert len(repo_agents) == 1 diff --git a/tests/unit/test_microagent_no_header.py b/tests/unit/test_microagent_no_header.py index 5d360a04dc..d7942834e2 100644 --- a/tests/unit/test_microagent_no_header.py +++ b/tests/unit/test_microagent_no_header.py @@ -1,7 +1,7 @@ from pathlib import Path -from openhands.microagent.microagent import BaseMicroAgent, RepoMicroAgent -from openhands.microagent.types import MicroAgentType +from openhands.microagent.microagent import BaseMicroagent, RepoMicroagent +from openhands.microagent.types import MicroagentType def test_load_markdown_without_frontmatter(): @@ -10,13 +10,13 @@ def test_load_markdown_without_frontmatter(): path = Path('test.md') # Load the agent from content - agent = BaseMicroAgent.load(path, content) + agent = BaseMicroagent.load(path, content) # Verify it's loaded as a repo agent with default values - assert isinstance(agent, RepoMicroAgent) + assert isinstance(agent, RepoMicroagent) assert agent.name == 'default' assert agent.content == content - assert agent.type == MicroAgentType.REPO_KNOWLEDGE + assert agent.type == MicroagentType.REPO_KNOWLEDGE assert agent.metadata.agent == 'CodeActAgent' assert agent.metadata.version == '1.0.0' @@ -29,16 +29,16 @@ def test_load_markdown_with_empty_frontmatter(): path = Path('test.md') # Load the agent from content - agent = BaseMicroAgent.load(path, content) + agent = BaseMicroagent.load(path, content) # Verify it's loaded as a repo agent with default values - assert isinstance(agent, RepoMicroAgent) + assert isinstance(agent, RepoMicroagent) assert agent.name == 'default' assert ( agent.content == '# Test Content\nThis is a test markdown file with empty frontmatter.' ) - assert agent.type == MicroAgentType.REPO_KNOWLEDGE + assert agent.type == MicroagentType.REPO_KNOWLEDGE assert agent.metadata.agent == 'CodeActAgent' assert agent.metadata.version == '1.0.0' @@ -53,16 +53,16 @@ This is a test markdown file with partial frontmatter.""" path = Path('test.md') # Load the agent from content - agent = BaseMicroAgent.load(path, content) + agent = BaseMicroagent.load(path, content) # Verify it uses provided name but default values for other fields - assert isinstance(agent, RepoMicroAgent) + assert isinstance(agent, RepoMicroagent) assert agent.name == 'custom_name' assert ( agent.content == '# Test Content\nThis is a test markdown file with partial frontmatter.' ) - assert agent.type == MicroAgentType.REPO_KNOWLEDGE + assert agent.type == MicroagentType.REPO_KNOWLEDGE assert agent.metadata.agent == 'CodeActAgent' assert agent.metadata.version == '1.0.0' @@ -80,15 +80,15 @@ This is a test markdown file with full frontmatter.""" path = Path('test.md') # Load the agent from content - agent = BaseMicroAgent.load(path, content) + agent = BaseMicroagent.load(path, content) # Verify all provided values are used - assert isinstance(agent, RepoMicroAgent) + assert isinstance(agent, RepoMicroagent) assert agent.name == 'test_agent' assert ( agent.content == '# Test Content\nThis is a test markdown file with full frontmatter.' ) - assert agent.type == MicroAgentType.REPO_KNOWLEDGE + assert agent.type == MicroagentType.REPO_KNOWLEDGE assert agent.metadata.agent == 'CustomAgent' assert agent.metadata.version == '2.0.0' diff --git a/tests/unit/test_microagent_utils.py b/tests/unit/test_microagent_utils.py index 64d423b469..ce52c7a5f8 100644 --- a/tests/unit/test_microagent_utils.py +++ b/tests/unit/test_microagent_utils.py @@ -5,14 +5,14 @@ from pathlib import Path import pytest -from openhands.core.exceptions import MicroAgentValidationError +from openhands.core.exceptions import MicroagentValidationError from openhands.microagent import ( - BaseMicroAgent, - KnowledgeMicroAgent, - MicroAgentMetadata, - MicroAgentType, - RepoMicroAgent, - TaskMicroAgent, + BaseMicroagent, + KnowledgeMicroagent, + MicroagentMetadata, + MicroagentType, + RepoMicroagent, + TaskMicroagent, load_microagents_from_dir, ) @@ -26,11 +26,11 @@ def test_legacy_micro_agent_load(tmp_path): legacy_file = tmp_path / '.openhands_instructions' legacy_file.write_text(CONTENT) - micro_agent = BaseMicroAgent.load(legacy_file) - assert isinstance(micro_agent, RepoMicroAgent) + micro_agent = BaseMicroagent.load(legacy_file) + assert isinstance(micro_agent, RepoMicroagent) assert micro_agent.name == 'repo_legacy' assert micro_agent.content == CONTENT - assert micro_agent.type == MicroAgentType.REPO_KNOWLEDGE + assert micro_agent.type == MicroagentType.REPO_KNOWLEDGE @pytest.fixture @@ -89,14 +89,14 @@ Test task content def test_knowledge_agent(): """Test knowledge agent functionality.""" - agent = KnowledgeMicroAgent( + agent = KnowledgeMicroagent( name='test', content='Test content', - metadata=MicroAgentMetadata( - name='test', type=MicroAgentType.KNOWLEDGE, triggers=['test', 'pytest'] + metadata=MicroagentMetadata( + name='test', type=MicroagentType.KNOWLEDGE, triggers=['test', 'pytest'] ), source='test.md', - type=MicroAgentType.KNOWLEDGE, + type=MicroagentType.KNOWLEDGE, ) assert agent.match_trigger('running a test') == 'test' @@ -114,18 +114,18 @@ def test_load_microagents(temp_microagents_dir): # Check knowledge agents assert len(knowledge_agents) == 1 agent = knowledge_agents['test_knowledge_agent'] - assert isinstance(agent, KnowledgeMicroAgent) + assert isinstance(agent, KnowledgeMicroagent) assert 'test' in agent.triggers # Check repo agents assert len(repo_agents) == 1 agent = repo_agents['test_repo_agent'] - assert isinstance(agent, RepoMicroAgent) + assert isinstance(agent, RepoMicroagent) # Check task agents assert len(task_agents) == 1 agent = task_agents['test_task'] - assert isinstance(agent, TaskMicroAgent) + assert isinstance(agent, TaskMicroagent) def test_invalid_agent_type(temp_microagents_dir): @@ -141,8 +141,8 @@ Invalid agent content """ (temp_microagents_dir / 'invalid.md').write_text(invalid_agent) - with pytest.raises(MicroAgentValidationError): - BaseMicroAgent.load(temp_microagents_dir / 'invalid.md') + with pytest.raises(MicroagentValidationError): + BaseMicroagent.load(temp_microagents_dir / 'invalid.md') def test_load_microagents_with_nested_dirs(temp_microagents_dir): @@ -172,7 +172,7 @@ Testing nested directory loading. # Check that we can find the nested agent assert len(knowledge_agents) == 2 # Original + nested agent = knowledge_agents['nested_knowledge_agent'] - assert isinstance(agent, KnowledgeMicroAgent) + assert isinstance(agent, KnowledgeMicroagent) assert 'nested' in agent.triggers @@ -203,5 +203,5 @@ Testing loading with trailing slashes. # Check that we can find the agent despite trailing slashes assert len(knowledge_agents) == 2 # Original + trailing agent = knowledge_agents['trailing_knowledge_agent'] - assert isinstance(agent, KnowledgeMicroAgent) + assert isinstance(agent, KnowledgeMicroagent) assert 'trailing' in agent.triggers diff --git a/tests/unit/test_prompt_manager.py b/tests/unit/test_prompt_manager.py index 7ca79bfe8c..6abb648f03 100644 --- a/tests/unit/test_prompt_manager.py +++ b/tests/unit/test_prompt_manager.py @@ -6,7 +6,7 @@ import pytest from openhands.controller.state.state import State from openhands.core.message import Message, TextContent from openhands.events.observation.agent import MicroagentKnowledge -from openhands.microagent import BaseMicroAgent +from openhands.microagent import BaseMicroagent from openhands.utils.prompt import PromptManager, RepositoryInfo, RuntimeInfo @@ -72,7 +72,7 @@ def test_prompt_manager_file_not_found(prompt_dir): """Test PromptManager behavior when a template file is not found.""" # Test with a non-existent template with pytest.raises(FileNotFoundError): - BaseMicroAgent.load( + BaseMicroagent.load( os.path.join(prompt_dir, 'micro', 'non_existent_microagent.md') )