Skip to content

Commit d77d0e6

Browse files
authored
Merge pull request #24 from zhujian0805/main
feat: Implement agent metadata pulling using awesome-claude-agents approach
2 parents b76aaab + 7a47c88 commit d77d0e6

2 files changed

Lines changed: 383 additions & 39 deletions

File tree

code_assistant_manager/agents/manager.py

Lines changed: 96 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .gemini import GeminiAgentHandler
2020
from .opencode import OpenCodeAgentHandler
2121
from .models import Agent, AgentRepo
22+
from ..fetcher import Fetcher
2223

2324
logger = logging.getLogger(__name__)
2425

@@ -314,55 +315,111 @@ def _fetch_agents_from_repo(
314315
Returns:
315316
List of agents found
316317
"""
317-
temp_dir, actual_branch = handler._download_repo(
318-
repo.owner, repo.name, repo.branch
319-
)
318+
# Use the new Fetcher class similar to awesome-claude-agents
319+
fetcher = Fetcher()
320+
321+
repo_data = {
322+
"owner": repo.owner,
323+
"name": repo.name,
324+
"branch": repo.branch,
325+
"agentsPath": repo.agents_path or "agents"
326+
}
327+
328+
agents_data = fetcher.fetch_agents_from_repo(repo_data)
320329
agents = []
321330

331+
for agent_data in agents_data:
332+
# Convert to Agent model
333+
filename = agent_data["file_path"].split("/")[-1] if "/" in agent_data["file_path"] else agent_data["file_path"]
334+
335+
agent = Agent(
336+
key=f"{repo.owner}/{repo.name}:{agent_data['name']}",
337+
name=agent_data["name"],
338+
description=agent_data["description"],
339+
filename=filename,
340+
installed=False,
341+
repo_owner=repo.owner,
342+
repo_name=repo.name,
343+
repo_branch=repo.branch,
344+
agents_path=repo.agents_path,
345+
readme_url=f"https://github.com/{repo.owner}/{repo.name}/blob/{repo.branch}/{agent_data['file_path']}",
346+
tools=agent_data.get("source_data", {}).get("tools", []),
347+
color=agent_data.get("source_data", {}).get("color"),
348+
)
349+
agents.append(agent)
350+
logger.debug(f"Found agent: {agent.key}")
351+
352+
return agents
353+
354+
def fetch_agents_from_external_sources(self) -> List[Agent]:
355+
"""Fetch agents from external sources defined in agent_repos.json.
356+
357+
This uses the same method as awesome-claude-agents for fetching from
358+
external JSON sources.
359+
360+
Returns:
361+
List of discovered agents from all sources
362+
"""
363+
# Load the agent_repos.json file
364+
package_dir = Path(__file__).parent.parent
365+
repos_file = package_dir / "agent_repos.json"
366+
367+
if not repos_file.exists():
368+
logger.warning("agent_repos.json file not found")
369+
return []
370+
322371
try:
323-
scan_dir = temp_dir
324-
if repo.agents_path:
325-
scan_dir = temp_dir / repo.agents_path.strip("/")
372+
with open(repos_file, "r", encoding="utf-8") as f:
373+
repos_data = json.load(f)
374+
except Exception as e:
375+
logger.warning(f"Failed to load agent_repos.json: {e}")
376+
return []
326377

327-
if not scan_dir.exists():
328-
logger.warning(f"Agents path not found: {scan_dir}")
329-
return agents
378+
# Use the Fetcher to get agents from each repository
379+
fetcher = Fetcher()
380+
all_agents = []
381+
existing_agents = self._load_agents()
330382

331-
for agent_file in scan_dir.glob("*.md"):
332-
if not agent_file.is_file():
333-
continue
383+
for repo_id, repo_data in repos_data.items():
384+
if not repo_data.get("enabled", True):
385+
logger.debug(f"Skipping disabled repository: {repo_id}")
386+
continue
334387

335-
# Skip README files
336-
if agent_file.name.lower() in ["readme.md", "contributing.md"]:
337-
continue
388+
try:
389+
agents_data = fetcher.fetch_agents_from_repo(repo_data)
390+
for agent_data in agents_data:
391+
# Convert to Agent model
392+
filename = agent_data["file_path"].split("/")[-1] if "/" in agent_data["file_path"] else agent_data["file_path"]
393+
394+
agent_key = f"{repo_data['owner']}/{repo_data['name']}:{agent_data['name']}"
395+
396+
agent = Agent(
397+
key=agent_key,
398+
name=agent_data["name"],
399+
description=agent_data["description"],
400+
filename=filename,
401+
installed=existing_agents.get(agent_key, Agent("", "", "", "", False)).installed,
402+
repo_owner=repo_data["owner"],
403+
repo_name=repo_data["name"],
404+
repo_branch=repo_data.get("branch", "main"),
405+
agents_path=repo_data.get("agentsPath", "agents"),
406+
readme_url=f"https://github.com/{repo_data['owner']}/{repo_data['name']}/blob/{repo_data.get('branch', 'main')}/{agent_data['file_path']}",
407+
tools=agent_data.get("source_data", {}).get("tools", []),
408+
color=agent_data.get("source_data", {}).get("color"),
409+
)
410+
all_agents.append(agent)
338411

339-
meta = handler.parse_agent_metadata(agent_file)
340-
filename = agent_file.name
412+
logger.info(f"Found {len(agents_data)} agents in {repo_id}")
341413

342-
path_from_repo_root = agent_file.relative_to(temp_dir)
343-
readme_path = str(path_from_repo_root).replace("\\", "/")
414+
except Exception as e:
415+
logger.warning(f"Failed to fetch agents from {repo_id}: {e}")
344416

345-
agent = Agent(
346-
key=f"{repo.owner}/{repo.name}:{meta.get('name', filename.replace('.md', ''))}",
347-
name=meta.get("name", filename.replace(".md", "")),
348-
description=meta.get("description", ""),
349-
filename=filename,
350-
installed=False,
351-
repo_owner=repo.owner,
352-
repo_name=repo.name,
353-
repo_branch=actual_branch,
354-
agents_path=repo.agents_path,
355-
readme_url=f"https://github.com/{repo.owner}/{repo.name}/blob/{actual_branch}/{readme_path}",
356-
tools=meta.get("tools", []),
357-
color=meta.get("color"),
358-
)
359-
agents.append(agent)
360-
logger.debug(f"Found agent: {agent.key}")
361-
finally:
362-
if temp_dir.exists():
363-
shutil.rmtree(temp_dir)
417+
# Update existing agents database
418+
for agent in all_agents:
419+
existing_agents[agent.key] = agent
420+
self._save_agents(existing_agents)
364421

365-
return agents
422+
return all_agents
366423

367424
def sync_installed_status(self, app_type: str = "claude") -> None:
368425
"""Sync the installed status of all agents.

0 commit comments

Comments
 (0)