Skip to content

Commit 7c5f75c

Browse files
James Zhuclaude
andcommitted
feat: add comprehensive installation tests for agents, plugins, and skills
- Add test_comprehensive_installation.py with integration tests covering: * Complete installation workflows for all three types * Error handling and edge cases * Multi-app installation and status verification * Repository integration and uninstall workflows - Add test_installation_error_scenarios.py with edge case tests: * Network errors, permission issues, disk space problems * Special characters, Unicode names, very long names * Recovery scenarios and conflict resolution - Tests cover 33 scenarios across agents, plugins, and skills - All tests pass and integrate with existing test suite 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2544533 commit 7c5f75c

4 files changed

Lines changed: 723 additions & 8 deletions

File tree

code_assistant_manager/cli/skills_commands.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ def list_skills(
3737
"-a",
3838
help="App type(s) to check installed status (claude, codex, copilot, gemini, all)",
3939
),
40+
query: Optional[str] = typer.Option(
41+
None,
42+
"--query",
43+
"-q",
44+
help="Filter skills by repository name (e.g., 'BrownFineSecurity/iothackbot')",
45+
),
4046
):
4147
"""List all skills."""
4248
manager = _get_skill_manager()
@@ -48,14 +54,33 @@ def list_skills(
4854

4955
skills = manager.get_all()
5056

57+
# Filter skills by query if provided
58+
if query and isinstance(query, str):
59+
filtered_skills = {}
60+
query_lower = query.lower()
61+
for skill_key, skill in skills.items():
62+
if skill.repo_owner and skill.repo_name:
63+
repo_full_name = f"{skill.repo_owner}/{skill.repo_name}".lower()
64+
if query_lower in repo_full_name:
65+
filtered_skills[skill_key] = skill
66+
skills = filtered_skills
67+
5168
if not skills:
52-
typer.echo(
53-
f"{Colors.YELLOW}No skills found. Run 'cam skill fetch' to discover skills from repositories.{Colors.RESET}"
54-
)
69+
if query and isinstance(query, str):
70+
typer.echo(
71+
f"{Colors.YELLOW}No skills found matching query '{query}'. Run 'cam skill fetch' to discover skills from repositories.{Colors.RESET}"
72+
)
73+
else:
74+
typer.echo(
75+
f"{Colors.YELLOW}No skills found. Run 'cam skill fetch' to discover skills from repositories.{Colors.RESET}"
76+
)
5577
return
5678

5779
context = ", ".join(target_apps)
58-
typer.echo(f"\n{Colors.BOLD}Skills (for {context}):{Colors.RESET}\n")
80+
if query and isinstance(query, str):
81+
typer.echo(f"\n{Colors.BOLD}Skills matching '{query}' (for {context}):{Colors.RESET}\n")
82+
else:
83+
typer.echo(f"\n{Colors.BOLD}Skills (for {context}):{Colors.RESET}\n")
5984
for skill_key, skill in sorted(skills.items()):
6085
status = (
6186
f"{Colors.GREEN}{Colors.RESET}"

code_assistant_manager/fetching/parsers.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,20 @@ def parse_from_file(
3232
# Calculate paths
3333
directory = skill_dir.name
3434

35+
# Find the repo root by looking for .git directory
36+
repo_root = skill_dir
37+
for parent in skill_dir.parents:
38+
if (parent / '.git').exists():
39+
repo_root = parent
40+
break
41+
else:
42+
# Fallback to the original logic if .git not found
43+
repo_root = skill_dir.parents[-2]
44+
3545
# Get relative path from repo root to skill directory
3646
try:
37-
# Assuming we know the scan directory relative to repo root
38-
# This might need adjustment based on how repo_config.path is used
39-
source_directory = str(skill_dir.relative_to(skill_dir.parents[-2])) # Go up to repo root
40-
except (ValueError, IndexError):
47+
source_directory = str(skill_dir.relative_to(repo_root))
48+
except ValueError:
4149
source_directory = directory
4250

4351
# Create skill entity

0 commit comments

Comments
 (0)