Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ lint:
ruff check --config ./python/pyproject.toml ./python/

test:
uv run pytest python/tests/
uv run pytest ./python
14 changes: 13 additions & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ dependencies = [
"tushare>=1.4.24",
"requests>=2.32.5",
"akshare>=1.17.44",
"agno>=1.8.2",
"agno[openai]>=1.8.2,<2.0",
]

[project.optional-dependencies]
Expand Down Expand Up @@ -64,3 +64,15 @@ exclude = [
"docs/**",
"**/docs/**",
]

[tool.pytest.ini_options]
norecursedirs = [
".venv",
"venv",
"build",
"dist",
"logs",
"third_party",
"examples",
"docs",
]
85 changes: 83 additions & 2 deletions python/uv.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions python/valuecell/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@
"__author__",
"__description__",
]

# registers agents on import
import valuecell.agents as _ # noqa: F401
61 changes: 61 additions & 0 deletions python/valuecell/agents/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""
Auto-import all agents to ensure they are registered with the AgentRegistry.
This module dynamically discovers and imports all agent classes.
"""

import importlib
import inspect
import pkgutil
from pathlib import Path
from typing import List

from valuecell.core.agent.types import BaseAgent


def _discover_and_import_agents() -> List[str]:
"""
Dynamically discover and import all agent modules in this package.

Returns:
List of agent class names that were imported
"""
imported_agents = []
current_package = __name__
current_path = Path(__file__).parent

# Iterate through all Python files in the current directory
for _, module_name, _ in pkgutil.iter_modules([str(current_path)]):
if module_name.startswith("_"):
# Skip private modules
continue

try:
# Import the module
module = importlib.import_module(f"{current_package}.{module_name}")

# Find all classes in the module that inherit from BaseAgent
for name, obj in inspect.getmembers(module, inspect.isclass):
if (
obj.__module__ == module.__name__
and issubclass(obj, BaseAgent)
and obj != BaseAgent
):
imported_agents.append(name)
# Make the class available at package level
globals()[name] = obj

except Exception as e:
# Log import errors but continue with other modules
import logging

logger = logging.getLogger(__name__)
logger.warning(f"Failed to import module {module_name}: {e}")

return imported_agents


# Auto-import all agents
_imported_agent_names = _discover_and_import_agents()

# Export all discovered agents for convenient access
__all__ = _imported_agent_names
15 changes: 15 additions & 0 deletions python/valuecell/agents/hello_world.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from valuecell.core.agent.decorator import serve
from valuecell.core.agent.types import BaseAgent


@serve()
class HelloWorldAgent(BaseAgent):
"""
A simple Hello World Agent that responds with a greeting message.
"""

async def stream(self, query, session_id, task_id):
return {
"content": f"Hello! You said: {query}",
"is_task_complete": True,
}
Empty file.
21 changes: 21 additions & 0 deletions python/valuecell/agents/tests/test_import.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pytest
from valuecell.core.agent.connect import RemoteConnections


@pytest.mark.asyncio
async def test_run_hello_world():
connections = RemoteConnections()
name = "HelloWorldAgent"
try:
available = connections.list_available_agents()
assert name in available

url = await connections.start_agent("HelloWorldAgent")
assert isinstance(url, str) and url

client = await connections.get_client("HelloWorldAgent")
task, event = await client.send_message("Hi there!")
assert task is not None
assert event is None
finally:
await connections.stop_all()