diff --git a/ra_aid/__main__.py b/ra_aid/__main__.py index 97243e0..6069cf0 100644 --- a/ra_aid/__main__.py +++ b/ra_aid/__main__.py @@ -280,6 +280,11 @@ Examples: action="store_true", help="Delete the project database file (.ra-aid/pk.db) before starting, effectively wiping all stored memory", ) + parser.add_argument( + "--show-thoughts", + action="store_true", + help="Display model thinking content extracted from think tags when supported by the model", + ) if args is None: args = sys.argv[1:] parsed_args = parser.parse_args(args) @@ -563,6 +568,7 @@ def main(): config_repo.set("temperature", args.temperature) config_repo.set("experimental_fallback_handler", args.experimental_fallback_handler) config_repo.set("web_research_enabled", web_research_enabled) + config_repo.set("show_thoughts", args.show_thoughts) # Build status panel with memory statistics status = build_status() @@ -635,6 +641,7 @@ def main(): config_repo.set("expert_provider", args.expert_provider) config_repo.set("expert_model", args.expert_model) config_repo.set("temperature", args.temperature) + config_repo.set("show_thoughts", args.show_thoughts) # Set modification tools based on use_aider flag set_modification_tools(args.use_aider) diff --git a/ra_aid/agent_backends/ciayn_agent.py b/ra_aid/agent_backends/ciayn_agent.py index 58ffab9..72d2609 100644 --- a/ra_aid/agent_backends/ciayn_agent.py +++ b/ra_aid/agent_backends/ciayn_agent.py @@ -635,7 +635,8 @@ class CiaynAgent: if supports_think_tag or supports_thinking: think_content, remaining_text = extract_think_tag(response.content) if think_content: - console.print(Panel(Markdown(think_content), title="💭 Thoughts")) + if self.config.get("show_thoughts", False): + console.print(Panel(Markdown(think_content), title="💭 Thoughts")) response.content = remaining_text # Check if the response is empty or doesn't contain a valid tool call diff --git a/ra_aid/tools/expert.py b/ra_aid/tools/expert.py index f5be3c6..2ccb330 100644 --- a/ra_aid/tools/expert.py +++ b/ra_aid/tools/expert.py @@ -255,9 +255,10 @@ def ask_expert(question: str) -> str: think_content, remaining_text = extract_think_tag(content) if think_content: logger.debug(f"Found think tag content ({len(think_content)} chars)") - console.print( - Panel(Markdown(think_content), title="💭 Thoughts", border_style="yellow") - ) + if get_config_repository().get("show_thoughts", False): + console.print( + Panel(Markdown(think_content), title="💭 Thoughts", border_style="yellow") + ) content = remaining_text else: logger.debug("No think tag content found in expert response") @@ -282,7 +283,7 @@ def ask_expert(question: str) -> str: logger.debug("Found structured response text") # Display thinking content in a separate panel if available - if thinking_content: + if thinking_content and get_config_repository().get("show_thoughts", False): logger.debug(f"Displaying structured thinking content ({len(thinking_content)} chars)") console.print( Panel(Markdown(thinking_content), title="Expert Thinking", border_style="yellow") diff --git a/tests/ra_aid/agent_backends/test_ciayn_agent_think_tag.py b/tests/ra_aid/agent_backends/test_ciayn_agent_think_tag.py index 302d532..80faf39 100644 --- a/tests/ra_aid/agent_backends/test_ciayn_agent_think_tag.py +++ b/tests/ra_aid/agent_backends/test_ciayn_agent_think_tag.py @@ -21,10 +21,11 @@ def test_stream_supports_think_tag(mock_get_model): mock_response = AIMessage(content="These are my thoughtsActual response") mock_model.invoke.return_value = mock_response - # Setup agent with config that supports think tags + # Setup agent with config that supports think tags and show_thoughts config = { "provider": "openai-compatible", - "model": "qwen-qwq-32b" + "model": "qwen-qwq-32b", + "show_thoughts": True } agent = CiaynAgent(mock_model, [], config=config) @@ -98,10 +99,11 @@ def test_stream_with_no_think_tags(mock_get_model): mock_response = AIMessage(content="Actual response without tags") mock_model.invoke.return_value = mock_response - # Setup agent with config that supports think tags + # Setup agent with config that supports think tags and show_thoughts config = { "provider": "openai-compatible", - "model": "qwen-qwq-32b" + "model": "qwen-qwq-32b", + "show_thoughts": True } agent = CiaynAgent(mock_model, [], config=config) diff --git a/tests/ra_aid/test_show_thoughts.py b/tests/ra_aid/test_show_thoughts.py new file mode 100644 index 0000000..03ca51b --- /dev/null +++ b/tests/ra_aid/test_show_thoughts.py @@ -0,0 +1,83 @@ +"""Unit tests for the --show-thoughts CLI flag.""" + +import pytest +from unittest.mock import patch, MagicMock + +from ra_aid.__main__ import parse_arguments + + +def test_show_thoughts_flag(): + """Test that the --show-thoughts flag is correctly parsed.""" + # Test default value (False) + args = parse_arguments(["-m", "test message"]) + assert args.show_thoughts is False + + # Test with flag (True) + args = parse_arguments(["-m", "test message", "--show-thoughts"]) + assert args.show_thoughts is True + + +@pytest.fixture(autouse=True) +def mock_config_repository(): + """Mock the ConfigRepository to avoid database operations during tests""" + with patch('ra_aid.database.repositories.config_repository.config_repo_var') as mock_repo_var: + # Setup a mock repository + mock_repo = MagicMock() + + # Create a dictionary to simulate config + config = {} + + # Setup get method to return config values + def get_config(key, default=None): + return config.get(key, default) + mock_repo.get.side_effect = get_config + + # Setup set method to update config values + def set_config(key, value): + config[key] = value + mock_repo.set.side_effect = set_config + + # Setup update method to update multiple config values + def update_config(config_dict): + config.update(config_dict) + mock_repo.update.side_effect = update_config + + # Setup get_all method to return the config dict + def get_all_config(): + return config.copy() + mock_repo.get_all.side_effect = get_all_config + + # Make the mock context var return our mock repo + mock_repo_var.get.return_value = mock_repo + + yield mock_repo + + +def test_show_thoughts_config(mock_config_repository): + """Test that the show_thoughts flag is correctly stored in config.""" + import sys + from unittest.mock import patch + + from ra_aid.__main__ import main + + # Reset mocks + mock_config_repository.set.reset_mock() + + # For testing, we need to patch ConfigRepositoryManager.__enter__ to return our mock + with patch('ra_aid.database.repositories.config_repository.ConfigRepositoryManager.__enter__', return_value=mock_config_repository): + # Test with --show-thoughts flag + with patch.object(sys, "argv", ["ra-aid", "-m", "test message", "--show-thoughts"]): + with patch("ra_aid.__main__.run_research_agent", return_value=None): + main() + # Verify the show_thoughts flag is set to True in config + mock_config_repository.set.assert_any_call("show_thoughts", True) + + # Reset mocks + mock_config_repository.set.reset_mock() + + # Test without --show-thoughts flag (default: False) + with patch.object(sys, "argv", ["ra-aid", "-m", "test message"]): + with patch("ra_aid.__main__.run_research_agent", return_value=None): + main() + # Verify the show_thoughts flag is set to False in config + mock_config_repository.set.assert_any_call("show_thoughts", False) \ No newline at end of file