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}", )