diff --git a/ra_aid/env.py b/ra_aid/env.py index 8fa7e7d..686045b 100644 --- a/ra_aid/env.py +++ b/ra_aid/env.py @@ -95,11 +95,11 @@ def validate_environment(args) -> Tuple[bool, List[str], bool, List[str]]: # Check web research dependencies web_research_missing = [] + web_research_enabled = False + if not os.environ.get('TAVILY_API_KEY'): web_research_missing.append('TAVILY_API_KEY environment variable is not set') - - web_research_enabled = True - if web_research_missing: - web_research_enabled = False + else: + web_research_enabled = True return expert_enabled, expert_missing, web_research_enabled, web_research_missing diff --git a/tests/ra_aid/test_env.py b/tests/ra_aid/test_env.py index fe23ba7..3be98e4 100644 --- a/tests/ra_aid/test_env.py +++ b/tests/ra_aid/test_env.py @@ -18,7 +18,7 @@ def clean_env(monkeypatch): env_vars = [ 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY', 'OPENROUTER_API_KEY', 'OPENAI_API_BASE', 'EXPERT_ANTHROPIC_API_KEY', 'EXPERT_OPENAI_API_KEY', - 'EXPERT_OPENROUTER_API_KEY', 'EXPERT_OPENAI_API_BASE' + 'EXPERT_OPENROUTER_API_KEY', 'EXPERT_OPENAI_API_BASE', 'TAVILY_API_KEY' ] for var in env_vars: monkeypatch.delenv(var, raising=False) @@ -32,9 +32,11 @@ def test_anthropic_validation(clean_env, monkeypatch): # Should pass with API key monkeypatch.setenv('ANTHROPIC_API_KEY', 'test-key') - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert not expert_enabled - assert 'EXPERT_OPENAI_API_KEY environment variable is not set' in missing + assert 'EXPERT_OPENAI_API_KEY environment variable is not set' in expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing def test_openai_validation(clean_env, monkeypatch): args = MockArgs(provider="openai", expert_provider="openai") @@ -45,9 +47,11 @@ def test_openai_validation(clean_env, monkeypatch): # Should pass with API key and enable expert mode with fallback monkeypatch.setenv('OPENAI_API_KEY', 'test-key') - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'test-key' def test_openai_compatible_validation(clean_env, monkeypatch): @@ -64,9 +68,11 @@ def test_openai_compatible_validation(clean_env, monkeypatch): # Should pass with both API key and base URL monkeypatch.setenv('OPENAI_API_BASE', 'http://test') - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'test-key' assert os.environ.get('EXPERT_OPENAI_API_BASE') == 'http://test' @@ -77,16 +83,20 @@ def test_expert_fallback(clean_env, monkeypatch): monkeypatch.setenv('OPENAI_API_KEY', 'test-key') # Should enable expert mode with fallback - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'test-key' # Should use explicit expert key if available monkeypatch.setenv('EXPERT_OPENAI_API_KEY', 'expert-key') - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'expert-key' def test_cross_provider_fallback(clean_env, monkeypatch): @@ -98,9 +108,11 @@ def test_cross_provider_fallback(clean_env, monkeypatch): monkeypatch.setenv('ANTHROPIC_API_KEY', 'anthropic-key') # Should enable expert mode with fallback to ANTHROPIC base key - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_ANTHROPIC_API_KEY') == 'anthropic-key' # Try with openai-compatible expert provider @@ -108,9 +120,11 @@ def test_cross_provider_fallback(clean_env, monkeypatch): monkeypatch.setenv('OPENAI_API_KEY', 'openai-key') monkeypatch.setenv('OPENAI_API_BASE', 'http://test') - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'openai-key' assert os.environ.get('EXPERT_OPENAI_API_BASE') == 'http://test' @@ -122,9 +136,11 @@ def test_no_warning_on_fallback(clean_env, monkeypatch): monkeypatch.setenv('OPENAI_API_KEY', 'test-key') # Should enable expert mode with fallback and no warnings - expert_enabled, expert_missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled assert not expert_missing # List should be empty + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'test-key' def test_different_providers_no_expert_key(clean_env, monkeypatch): @@ -136,9 +152,11 @@ def test_different_providers_no_expert_key(clean_env, monkeypatch): monkeypatch.setenv('OPENAI_API_KEY', 'openai-key') # Should enable expert mode and use base OPENAI key - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'openai-key' def test_mixed_provider_openai_compatible(clean_env, monkeypatch): @@ -151,8 +169,10 @@ def test_mixed_provider_openai_compatible(clean_env, monkeypatch): monkeypatch.setenv('OPENAI_API_BASE', 'http://test') # Should enable expert mode and use base openai key and URL - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_research_enabled, web_research_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert not web_research_enabled + assert 'TAVILY_API_KEY environment variable is not set' in web_research_missing assert os.environ.get('EXPERT_OPENAI_API_KEY') == 'openai-key' assert os.environ.get('EXPERT_OPENAI_API_BASE') == 'http://test' diff --git a/tests/ra_aid/test_llm.py b/tests/ra_aid/test_llm.py index 85cf0e7..ee5197d 100644 --- a/tests/ra_aid/test_llm.py +++ b/tests/ra_aid/test_llm.py @@ -188,10 +188,13 @@ def test_environment_variable_precedence(clean_env, mock_openai, monkeypatch): # Set up base environment first monkeypatch.setenv("OPENAI_API_KEY", "base-key") monkeypatch.setenv("EXPERT_OPENAI_API_KEY", "expert-key") + monkeypatch.setenv("TAVILY_API_KEY", "tavily-key") args = Args(provider="openai", expert_provider="openai") - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_enabled, web_missing = validate_environment(args) assert expert_enabled - assert not missing + assert not expert_missing + assert web_enabled + assert not web_missing llm = initialize_expert_llm() mock_openai.assert_called_with( @@ -202,12 +205,16 @@ def test_environment_variable_precedence(clean_env, mock_openai, monkeypatch): # Test empty key validation monkeypatch.setenv("EXPERT_OPENAI_API_KEY", "") monkeypatch.delenv("OPENAI_API_KEY", raising=False) # Remove fallback + monkeypatch.delenv("TAVILY_API_KEY", raising=False) # Remove web research monkeypatch.setenv("ANTHROPIC_API_KEY", "anthropic-key") # Add for provider validation args = Args(provider="anthropic", expert_provider="openai") # Change base provider to avoid validation error - expert_enabled, missing = validate_environment(args) + expert_enabled, expert_missing, web_enabled, web_missing = validate_environment(args) assert not expert_enabled - assert len(missing) == 1 - assert missing[0] == "EXPERT_OPENAI_API_KEY environment variable is not set" + assert len(expert_missing) == 1 + assert expert_missing[0] == "EXPERT_OPENAI_API_KEY environment variable is not set" + assert not web_enabled + assert len(web_missing) == 1 + assert web_missing[0] == "TAVILY_API_KEY environment variable is not set" @pytest.fixture def mock_anthropic(): diff --git a/tests/ra_aid/test_tool_configs.py b/tests/ra_aid/test_tool_configs.py index a70f31b..40a1625 100644 --- a/tests/ra_aid/test_tool_configs.py +++ b/tests/ra_aid/test_tool_configs.py @@ -54,19 +54,19 @@ def test_get_implementation_tools(): def test_get_web_research_tools(): # Test with expert enabled tools = get_web_research_tools(expert_enabled=True) - assert len(tools) == 3 + assert len(tools) == 4 assert all(callable(tool) for tool in tools) # Get tool names and verify exact matches tool_names = [tool.name for tool in tools] - expected_names = ['emit_expert_context', 'ask_expert', 'web_search_tavily'] + expected_names = ['emit_expert_context', 'ask_expert', 'web_search_tavily', 'emit_research_notes'] assert sorted(tool_names) == sorted(expected_names) # Test without expert enabled tools_no_expert = get_web_research_tools(expert_enabled=False) - assert len(tools_no_expert) == 1 + assert len(tools_no_expert) == 2 assert all(callable(tool) for tool in tools_no_expert) - # Verify exact tool name when expert is disabled + # Verify exact tool names when expert is disabled tool_names_no_expert = [tool.name for tool in tools_no_expert] - assert tool_names_no_expert == ['web_search_tavily'] + assert sorted(tool_names_no_expert) == sorted(['web_search_tavily', 'emit_research_notes'])