- Formatted 103 files to comply with ruff format requirements - No code logic changes, only formatting/whitespace - Fixes CI formatting check failures
164 lines
6.1 KiB
Python
164 lines
6.1 KiB
Python
import pytest
|
|
|
|
from skill_seekers.cli.enhance_skill_local import AGENT_PRESETS, LocalSkillEnhancer
|
|
|
|
|
|
def _make_skill_dir(tmp_path):
|
|
skill_dir = tmp_path / "test_skill"
|
|
skill_dir.mkdir()
|
|
(skill_dir / "SKILL.md").write_text("# Test", encoding="utf-8")
|
|
return skill_dir
|
|
|
|
|
|
def _allow_executable(monkeypatch, name="my-agent"):
|
|
monkeypatch.setattr(
|
|
"skill_seekers.cli.enhance_skill_local.shutil.which",
|
|
lambda executable: f"/usr/bin/{executable}" if executable == name else None,
|
|
)
|
|
|
|
|
|
class TestMultiAgentSupport:
|
|
"""Test multi-agent enhancement support."""
|
|
|
|
def test_agent_presets_structure(self):
|
|
"""Verify AGENT_PRESETS has required fields."""
|
|
for preset in AGENT_PRESETS.values():
|
|
assert "display_name" in preset
|
|
assert "command" in preset
|
|
assert "supports_skip_permissions" in preset
|
|
assert isinstance(preset["command"], list)
|
|
assert len(preset["command"]) > 0
|
|
|
|
def test_build_agent_command_claude(self, tmp_path):
|
|
"""Test Claude Code command building."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
enhancer = LocalSkillEnhancer(skill_dir, agent="claude")
|
|
prompt_file = str(tmp_path / "prompt.txt")
|
|
|
|
cmd_parts, uses_file = enhancer._build_agent_command(prompt_file, True)
|
|
|
|
assert cmd_parts[0] == "claude"
|
|
assert "--dangerously-skip-permissions" in cmd_parts
|
|
assert prompt_file in cmd_parts
|
|
assert uses_file is True
|
|
|
|
def test_build_agent_command_codex(self, tmp_path):
|
|
"""Test Codex CLI command building."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
enhancer = LocalSkillEnhancer(skill_dir, agent="codex")
|
|
prompt_file = str(tmp_path / "prompt.txt")
|
|
|
|
cmd_parts, uses_file = enhancer._build_agent_command(prompt_file, False)
|
|
|
|
assert cmd_parts[0] == "codex"
|
|
assert "exec" in cmd_parts
|
|
assert "--full-auto" in cmd_parts
|
|
assert "--skip-git-repo-check" in cmd_parts
|
|
assert uses_file is False
|
|
|
|
def test_build_agent_command_custom_with_placeholder(self, tmp_path, monkeypatch):
|
|
"""Test custom command with {prompt_file} placeholder."""
|
|
_allow_executable(monkeypatch, name="my-agent")
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
enhancer = LocalSkillEnhancer(
|
|
skill_dir,
|
|
agent="custom",
|
|
agent_cmd="my-agent --input {prompt_file}",
|
|
)
|
|
prompt_file = str(tmp_path / "prompt.txt")
|
|
|
|
cmd_parts, uses_file = enhancer._build_agent_command(prompt_file, False)
|
|
|
|
assert cmd_parts[0] == "my-agent"
|
|
assert "--input" in cmd_parts
|
|
assert prompt_file in cmd_parts
|
|
assert uses_file is True
|
|
|
|
def test_custom_agent_requires_command(self, tmp_path):
|
|
"""Test custom agent fails without --agent-cmd."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
with pytest.raises(ValueError, match="Custom agent requires --agent-cmd"):
|
|
LocalSkillEnhancer(skill_dir, agent="custom")
|
|
|
|
def test_invalid_agent_name(self, tmp_path):
|
|
"""Test invalid agent name raises error."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
with pytest.raises(ValueError, match="Unknown agent"):
|
|
LocalSkillEnhancer(skill_dir, agent="invalid-agent")
|
|
|
|
def test_agent_normalization(self, tmp_path):
|
|
"""Test agent name normalization (aliases)."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
for alias in ["claude-code", "claude_code", "CLAUDE"]:
|
|
enhancer = LocalSkillEnhancer(skill_dir, agent=alias)
|
|
assert enhancer.agent == "claude"
|
|
|
|
def test_environment_variable_agent(self, tmp_path, monkeypatch):
|
|
"""Test SKILL_SEEKER_AGENT environment variable."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
monkeypatch.setenv("SKILL_SEEKER_AGENT", "codex")
|
|
enhancer = LocalSkillEnhancer(skill_dir)
|
|
|
|
assert enhancer.agent == "codex"
|
|
|
|
def test_environment_variable_custom_command(self, tmp_path, monkeypatch):
|
|
"""Test SKILL_SEEKER_AGENT_CMD environment variable."""
|
|
_allow_executable(monkeypatch, name="my-agent")
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
monkeypatch.setenv("SKILL_SEEKER_AGENT", "custom")
|
|
monkeypatch.setenv("SKILL_SEEKER_AGENT_CMD", "my-agent {prompt_file}")
|
|
|
|
enhancer = LocalSkillEnhancer(skill_dir)
|
|
assert enhancer.agent == "custom"
|
|
assert enhancer.agent_cmd == "my-agent {prompt_file}"
|
|
|
|
def test_rejects_command_with_semicolon(self, tmp_path):
|
|
"""Test rejection of commands with shell metacharacters."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
with pytest.raises(ValueError, match="dangerous shell characters"):
|
|
LocalSkillEnhancer(
|
|
skill_dir,
|
|
agent="custom",
|
|
agent_cmd="evil-cmd; rm -rf /",
|
|
)
|
|
|
|
def test_rejects_command_with_pipe(self, tmp_path):
|
|
"""Test rejection of commands with pipe."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
with pytest.raises(ValueError, match="dangerous shell characters"):
|
|
LocalSkillEnhancer(
|
|
skill_dir,
|
|
agent="custom",
|
|
agent_cmd="cmd | malicious",
|
|
)
|
|
|
|
def test_rejects_command_with_background_job(self, tmp_path):
|
|
"""Test rejection of commands with background job operator."""
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
with pytest.raises(ValueError, match="dangerous shell characters"):
|
|
LocalSkillEnhancer(
|
|
skill_dir,
|
|
agent="custom",
|
|
agent_cmd="cmd & malicious",
|
|
)
|
|
|
|
def test_rejects_missing_executable(self, tmp_path, monkeypatch):
|
|
"""Test rejection when executable is not found on PATH."""
|
|
monkeypatch.setattr("skill_seekers.cli.enhance_skill_local.shutil.which", lambda _exe: None)
|
|
skill_dir = _make_skill_dir(tmp_path)
|
|
|
|
with pytest.raises(ValueError, match="not found in PATH"):
|
|
LocalSkillEnhancer(
|
|
skill_dir,
|
|
agent="custom",
|
|
agent_cmd="missing-agent {prompt_file}",
|
|
)
|