syum-af commited on
Commit
7e1939b
·
1 Parent(s): 0d91ffe
CLAUDE.md CHANGED
@@ -31,12 +31,18 @@
31
  ```
32
  src/
33
  ├── agents/
34
- ── code_analyzer.py # CodeAnalyzerAgent for business logic extraction
 
 
 
 
35
  └── main.py # CLI interface for development/testing
36
  tests/
37
  ├── test_code_analyzer_agent.py # Unit tests for CodeAnalyzerAgent
 
 
38
  └── tictactoe.ads # Sample Ada file for testing
39
- app.py # Gradio web interface
40
  requirements.txt # Generated from uv dependencies
41
  pyproject.toml # Project configuration and dependencies
42
  .env # Environment configuration
@@ -48,6 +54,12 @@ pyproject.toml # Project configuration and dependencies
48
  * extract_business_logic() method analyzes Ada code via LLM
49
  * Returns structured JSON with core algorithms, data structures, business rules
50
  * Handles JSON parsing errors with fallback responses
 
 
 
 
 
 
51
 
52
  ## Hosting Platform
53
  * Hugging Face Spaces with Gradio SDK
 
31
  ```
32
  src/
33
  ├── agents/
34
+ ── code_analyzer.py # CodeAnalyzerAgent for business logic extraction
35
+ │ └── ada_converter.py # AdaConverterAgent for Ada to Python conversion
36
+ ├── tools/
37
+ │ └── project_handler.py # Zip extraction and file handling utilities
38
+ ├── ui.py # Gradio UI components and logic
39
  └── main.py # CLI interface for development/testing
40
  tests/
41
  ├── test_code_analyzer_agent.py # Unit tests for CodeAnalyzerAgent
42
+ ├── test_ada_converter_agent.py # Unit tests for AdaConverterAgent
43
+ ├── test_project_handler.py # Unit tests for project handler
44
  └── tictactoe.ads # Sample Ada file for testing
45
+ app.py # Application entry point and agent initialization
46
  requirements.txt # Generated from uv dependencies
47
  pyproject.toml # Project configuration and dependencies
48
  .env # Environment configuration
 
54
  * extract_business_logic() method analyzes Ada code via LLM
55
  * Returns structured JSON with core algorithms, data structures, business rules
56
  * Handles JSON parsing errors with fallback responses
57
+
58
+ * **AdaConverterAgent**: Converts Ada code to Python code
59
+ * Uses dependency injection pattern (model passed as parameter)
60
+ * convert_to_python() method converts Ada files to equivalent Python code
61
+ * Follows Ada to Python conversion principles (procedures→functions, packages→modules, etc.)
62
+ * Generates clean, PEP 8 compliant Python code with type hints
63
 
64
  ## Hosting Platform
65
  * Hugging Face Spaces with Gradio SDK
app.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  from dotenv import load_dotenv
3
  from smolagents import LiteLLMModel, OpenAIServerModel
4
  from src.agents.code_analyzer import CodeAnalyzerAgent
 
5
  from src.ui import create_interface
6
  from langfuse import get_client
7
  from openinference.instrumentation.smolagents import SmolagentsInstrumentor
@@ -19,8 +20,8 @@ else:
19
 
20
  SmolagentsInstrumentor().instrument()
21
 
22
- def initialize_analyzer():
23
- """Initialize the CodeAnalyzerAgent with appropriate model"""
24
  environment = os.getenv("ENVIRONMENT", "development")
25
  temperature = 0.1
26
 
@@ -38,10 +39,13 @@ def initialize_analyzer():
38
  temperature=temperature
39
  )
40
 
41
- return CodeAnalyzerAgent(model)
 
 
 
42
 
43
  # Create Gradio interface
44
  if __name__ == "__main__":
45
- analyzer = initialize_analyzer()
46
- app = create_interface(analyzer)
47
  app.launch()
 
2
  from dotenv import load_dotenv
3
  from smolagents import LiteLLMModel, OpenAIServerModel
4
  from src.agents.code_analyzer import CodeAnalyzerAgent
5
+ from src.agents.ada_converter import AdaConverterAgent
6
  from src.ui import create_interface
7
  from langfuse import get_client
8
  from openinference.instrumentation.smolagents import SmolagentsInstrumentor
 
20
 
21
  SmolagentsInstrumentor().instrument()
22
 
23
+ def initialize_agents():
24
+ """Initialize the agents with appropriate model"""
25
  environment = os.getenv("ENVIRONMENT", "development")
26
  temperature = 0.1
27
 
 
39
  temperature=temperature
40
  )
41
 
42
+ analyzer = CodeAnalyzerAgent(model)
43
+ converter = AdaConverterAgent(model)
44
+
45
+ return analyzer, converter
46
 
47
  # Create Gradio interface
48
  if __name__ == "__main__":
49
+ analyzer, converter = initialize_agents()
50
+ app = create_interface(analyzer, converter)
51
  app.launch()
src/agents/ada_converter.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Ada to Python converter agent."""
2
+
3
+ from smolagents import ToolCallingAgent, FinalAnswerTool
4
+
5
+
6
+ class AdaConverterAgent:
7
+ """Agent that converts Ada code to Python code."""
8
+
9
+ def __init__(self, model):
10
+ """Initialize the converter agent with a model."""
11
+ self.model = model
12
+ self.converter_agent = ToolCallingAgent(
13
+ model=self.model,
14
+ tools=[FinalAnswerTool()],
15
+ )
16
+
17
+ def convert_to_python(self, ada_file_path):
18
+ """Convert Ada file to Python code."""
19
+ try:
20
+ # Read the Ada file
21
+ with open(ada_file_path, 'r', encoding='utf-8') as f:
22
+ ada_code = f.read()
23
+
24
+ # Create the conversion prompt
25
+ prompt = f"""You are an expert Ada and Python programmer. Your task is to convert Ada code to equivalent Python code.
26
+
27
+ Key conversion principles:
28
+ 1. Convert Ada procedures to Python functions
29
+ 2. Convert Ada packages to Python modules/classes
30
+ 3. Convert Ada types to appropriate Python types
31
+ 4. Convert Ada control structures to Python equivalents
32
+ 5. Convert Ada exception handling to Python try/except
33
+ 6. Maintain the original logic and functionality
34
+ 7. Use Pythonic idioms and conventions
35
+ 8. Add appropriate type hints where beneficial
36
+
37
+ Always provide clean, readable Python code that follows PEP 8 standards.
38
+
39
+ Convert the following Ada code to Python:
40
+
41
+ ```ada
42
+ {ada_code}
43
+ ```
44
+
45
+ Please provide only the Python code without any explanations or markdown formatting."""
46
+
47
+ # Run the conversion
48
+ result = self.converter_agent.run(prompt)
49
+
50
+ # Extract response text like CodeAnalyzerAgent does
51
+ return self._extract_response_text(result)
52
+
53
+ except Exception as e:
54
+ return f"Error converting Ada code: {str(e)}"
55
+
56
+ def _extract_response_text(self, result) -> str:
57
+ """Extract text response from ToolCallingAgent result"""
58
+
59
+ print(f"_extract_response_text result = {result}")
60
+
61
+ if hasattr(result, 'messages') and result.messages:
62
+ return str(result.messages[-1].content)
63
+ else:
64
+ return str(result)
src/agents/code_analyzer.py CHANGED
@@ -8,10 +8,9 @@ This agent is responsible for:
8
  4. Generating analysis reports for conversion
9
  """
10
 
11
- from typing import Dict, Any, Union
12
  from pathlib import Path
13
  from smolagents import ToolCallingAgent, FinalAnswerTool
14
- import json
15
 
16
  class CodeAnalyzerAgent:
17
  """Agent specialized in analyzing Ada codebases"""
@@ -28,21 +27,14 @@ class CodeAnalyzerAgent:
28
  self.supported_extensions = ['.ads', '.adb', '.ada']
29
  self.analysis_results = {}
30
 
31
- def _parse_llm_response(self, response: str) -> Dict[str, Any]:
32
- """Parse LLM response and extract JSON analysis"""
33
- import json
34
- import re
35
-
36
- return json.loads(response);
37
-
38
  def _extract_response_text(self, result) -> str:
39
  """Extract text response from CodeAgent result"""
40
  if hasattr(result, 'messages') and result.messages:
41
  return str(result.messages[-1].content)
42
  else:
43
- return str(result).replace("\n", "")
44
 
45
- def extract_business_logic(self, ada_file_path: Union[Path, str]) -> Dict[str, Any]:
46
  """
47
  Extract business logic patterns from Ada file using LLM
48
 
@@ -70,10 +62,10 @@ class CodeAnalyzerAgent:
70
  # Use the code agent to analyze business logic
71
  result = self.code_agent.run(analysis_prompt)
72
 
73
- # Extract response text from RunResult
74
  response_text = self._extract_response_text(result)
75
 
76
- return json.loads(response_text)
77
 
78
  except Exception as e:
79
  print(f"LLM business logic analysis failed: {e}")
@@ -82,64 +74,62 @@ class CodeAnalyzerAgent:
82
  def _create_business_logic_prompt(self, file_path: Path, file_content: str) -> str:
83
  """Create structured business logic analysis prompt for LLM"""
84
  return f"""
85
- Analyze the business logic of this Ada code and return ONLY a JSON object.
86
- Do not write code or execute anything - just analyze and respond with JSON.
87
 
88
  Ada File: {file_path}
89
  Ada Code Content:
90
  {file_content}
91
 
92
- Return this exact JSON structure with your analysis:
93
- {{
94
- "core_algorithms": ["list of main algorithms and logic"],
95
- "data_structures": ["list of key data structures and types"],
96
- "business_rules": ["list of business rules and constraints"],
97
- "domain_concepts": ["list of domain-specific concepts"],
98
- "conversion_complexity": "low|medium|high",
99
- "recommended_approach": "description of conversion strategy"
100
- }}
101
- JSON key/values must be quoted with double-quotes, not single-quotes.
102
- JSON should never contain line-break (\n) in it.
103
-
104
- Focus on identifying:
105
- - Core business algorithms and computational logic from the Ada code
106
- - Important data structures, types, and their relationships
107
- - Business rules, constraints, and validation logic (especially SPARK contracts)
108
- - Domain-specific concepts and terminology
109
- - Complexity level for conversion to modern languages like Python/TypeScript
110
- - Recommended approach for modernization based on the code patterns
111
-
112
- Return ONLY the JSON object, nothing else.
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  """
114
 
115
- def _ensure_business_logic_structure(self, business_logic: Dict[str, Any]) -> Dict[str, Any]:
116
- """Ensure business logic response has required structure with defaults"""
117
- if not isinstance(business_logic, dict):
118
- business_logic = {}
119
-
120
- defaults = {
121
- 'core_algorithms': [],
122
- 'data_structures': [],
123
- 'business_rules': [],
124
- 'domain_concepts': [],
125
- 'conversion_complexity': 'medium',
126
- 'recommended_approach': 'Standard modernization approach recommended'
127
- }
128
-
129
- for key, default_value in defaults.items():
130
- if key not in business_logic:
131
- business_logic[key] = default_value
132
-
133
- return business_logic
134
 
135
- def _create_fallback_business_logic_with_error(self, error_msg: str) -> Dict[str, Any]:
136
  """Create fallback business logic response when analysis fails"""
137
- return {
138
- 'core_algorithms': [],
139
- 'data_structures': [],
140
- 'business_rules': [],
141
- 'domain_concepts': [],
142
- 'conversion_complexity': 'unknown',
143
- 'recommended_approach': 'Manual analysis recommended due to error',
144
- 'error': error_msg
145
- }
 
 
 
 
 
8
  4. Generating analysis reports for conversion
9
  """
10
 
11
+ from typing import Any, Union
12
  from pathlib import Path
13
  from smolagents import ToolCallingAgent, FinalAnswerTool
 
14
 
15
  class CodeAnalyzerAgent:
16
  """Agent specialized in analyzing Ada codebases"""
 
27
  self.supported_extensions = ['.ads', '.adb', '.ada']
28
  self.analysis_results = {}
29
 
 
 
 
 
 
 
 
30
  def _extract_response_text(self, result) -> str:
31
  """Extract text response from CodeAgent result"""
32
  if hasattr(result, 'messages') and result.messages:
33
  return str(result.messages[-1].content)
34
  else:
35
+ return str(result)
36
 
37
+ def extract_business_logic(self, ada_file_path: Union[Path, str]) -> str:
38
  """
39
  Extract business logic patterns from Ada file using LLM
40
 
 
62
  # Use the code agent to analyze business logic
63
  result = self.code_agent.run(analysis_prompt)
64
 
65
+ # Extract response text from RunResult (now markdown)
66
  response_text = self._extract_response_text(result)
67
 
68
+ return response_text
69
 
70
  except Exception as e:
71
  print(f"LLM business logic analysis failed: {e}")
 
74
  def _create_business_logic_prompt(self, file_path: Path, file_content: str) -> str:
75
  """Create structured business logic analysis prompt for LLM"""
76
  return f"""
77
+ Analyze the business logic of this Ada code and return a well-formatted markdown report.
78
+ Do not write code or execute anything - just analyze and respond with markdown.
79
 
80
  Ada File: {file_path}
81
  Ada Code Content:
82
  {file_content}
83
 
84
+ Structure your analysis as follows in markdown format:
85
+
86
+ # Business Logic Analysis
87
+
88
+ ## Core Algorithms
89
+ - List the main algorithms and computational logic found in the code
90
+ - Describe the key processing steps and workflows
91
+
92
+ ## Data Structures & Types
93
+ - Identify important data structures, types, and their relationships
94
+ - Note any custom types or complex data arrangements
95
+
96
+ ## Business Rules & Constraints
97
+ - List business rules, validation logic, and constraints
98
+ - Pay special attention to SPARK contracts and formal specifications
99
+ - Note any domain-specific rules or policies
100
+
101
+ ## Domain Concepts
102
+ - Identify domain-specific concepts and terminology
103
+ - Explain the business context and purpose of the code
104
+
105
+ ## Conversion Complexity
106
+ **Level**: Low/Medium/High
107
+
108
+ **Reasoning**: Explain why this complexity level was assigned
109
+
110
+ ## Recommended Approach
111
+ Describe the recommended strategy for converting this code to modern languages like Python/TypeScript, including:
112
+ - Key architectural considerations
113
+ - Potential challenges and solutions
114
+ - Suggested modernization patterns
115
+
116
+ Focus on providing clear, actionable insights for code modernization and conversion.
117
+ Return ONLY the markdown report, nothing else.
118
  """
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
+ def _create_fallback_business_logic_with_error(self, error_msg: str) -> str:
122
  """Create fallback business logic response when analysis fails"""
123
+ return f"""# Business Logic Analysis
124
+
125
+ ## Error
126
+ Analysis failed with error: {error_msg}
127
+
128
+ ## Recommended Approach
129
+ Manual analysis recommended due to analysis failure. Please review the Ada code manually or try again.
130
+
131
+ ## Next Steps
132
+ - Check if the file is valid Ada code
133
+ - Verify network connectivity for LLM access
134
+ - Consider using a different analysis approach
135
+ """
src/ui.py CHANGED
@@ -1,7 +1,6 @@
1
  """UI components and logic for the Ada Assistant Gradio interface."""
2
 
3
  import gradio as gr
4
- import json
5
  from src.tools.project_handler import unzip_project
6
 
7
 
@@ -23,14 +22,14 @@ def extract_project(file):
23
  def analyze_ada_file(file, analyzer):
24
  """Analyze uploaded Ada file and extract business logic"""
25
  try:
26
- # Analyze the uploaded file
27
  result = analyzer.extract_business_logic(file.name)
28
 
29
- # Format result for display
30
- return json.dumps(result, indent=2)
31
 
32
  except Exception as e:
33
- return f"Error analyzing file: {str(e)}"
34
 
35
 
36
  def handle_zip_upload(zip_file):
@@ -47,23 +46,19 @@ def handle_zip_upload(zip_file):
47
  return None, f"Error processing zip file: {str(e)}"
48
 
49
 
50
- def create_file_selection_handler(analyzer):
51
- """Create file selection handler with analyzer dependency"""
52
  def handle_file_selection(selected_file):
53
  """Handle file selection from FileExplorer"""
54
 
55
  if not selected_file:
56
- return "", "", gr.Code(visible=False), gr.JSON(visible=False)
57
 
58
  # Check if it's an Ada file
59
  if not (selected_file.endswith('.ads') or selected_file.endswith('.adb')):
60
- return "", "", gr.Code(visible=False), gr.JSON(visible=False)
61
 
62
  try:
63
- # Read the Ada source code
64
- with open(selected_file, 'r', encoding='utf-8') as f:
65
- source_code = f.read()
66
-
67
  # Create a mock file object for analyze_ada_file
68
  class MockFile:
69
  def __init__(self, name):
@@ -71,20 +66,18 @@ def create_file_selection_handler(analyzer):
71
 
72
  mock_file = MockFile(selected_file)
73
 
74
- # Analyze the Ada file
75
  analysis_result = analyze_ada_file(mock_file, analyzer)
 
 
 
76
 
77
- # Try to parse analysis result as JSON, fallback to string display
78
- try:
79
- parsed_result = json.loads(analysis_result)
80
-
81
- return parsed_result
82
- except:
83
- # If not valid JSON, display as text
84
- return {"analysis": analysis_result}
85
 
86
  except Exception as e:
87
- return {"error": f"Error processing file: {str(e)}"}
 
88
 
89
  return handle_file_selection
90
 
@@ -96,7 +89,7 @@ def update_explorer(path):
96
  return gr.FileExplorer(visible=False)
97
 
98
 
99
- def create_interface(analyzer):
100
  """Create the main Gradio interface"""
101
  with gr.Blocks(title="Ada Assistant - Project Analyzer") as app:
102
  gr.Markdown("# Ada Assistant - Project Analyzer")
@@ -129,9 +122,18 @@ def create_interface(analyzer):
129
  with gr.Row():
130
  with gr.Column(scale=1):
131
  # Analysis results display
132
- analysis_results = gr.JSON(
133
  label="Business Logic Analysis",
134
- visible=True
 
 
 
 
 
 
 
 
 
135
  )
136
 
137
  # Hidden state to store extracted path
@@ -152,11 +154,11 @@ def create_interface(analyzer):
152
  )
153
 
154
  # Handle file selection
155
- handle_file_selection = create_file_selection_handler(analyzer)
156
  file_explorer.change(
157
  fn=handle_file_selection,
158
  inputs=[file_explorer],
159
- outputs=[analysis_results]
160
  )
161
 
162
  return app
 
1
  """UI components and logic for the Ada Assistant Gradio interface."""
2
 
3
  import gradio as gr
 
4
  from src.tools.project_handler import unzip_project
5
 
6
 
 
22
  def analyze_ada_file(file, analyzer):
23
  """Analyze uploaded Ada file and extract business logic"""
24
  try:
25
+ # Analyze the uploaded file (now returns markdown)
26
  result = analyzer.extract_business_logic(file.name)
27
 
28
+ # Return markdown result directly
29
+ return result
30
 
31
  except Exception as e:
32
+ return f"# Error\n\nError analyzing file: {str(e)}"
33
 
34
 
35
  def handle_zip_upload(zip_file):
 
46
  return None, f"Error processing zip file: {str(e)}"
47
 
48
 
49
+ def create_file_selection_handler(analyzer, converter):
50
+ """Create file selection handler with analyzer and converter dependencies"""
51
  def handle_file_selection(selected_file):
52
  """Handle file selection from FileExplorer"""
53
 
54
  if not selected_file:
55
+ return "", "", gr.Markdown(visible=False), gr.Code(visible=False)
56
 
57
  # Check if it's an Ada file
58
  if not (selected_file.endswith('.ads') or selected_file.endswith('.adb')):
59
+ return "", "", gr.Markdown(visible=False), gr.Code(visible=False)
60
 
61
  try:
 
 
 
 
62
  # Create a mock file object for analyze_ada_file
63
  class MockFile:
64
  def __init__(self, name):
 
66
 
67
  mock_file = MockFile(selected_file)
68
 
69
+ # Analyze the Ada file (now returns markdown)
70
  analysis_result = analyze_ada_file(mock_file, analyzer)
71
+
72
+ # Convert Ada file to Python
73
+ python_code = converter.convert_to_python(selected_file)
74
 
75
+ # Return markdown analysis and python code
76
+ return analysis_result, python_code, gr.Markdown(visible=True), gr.Code(visible=True)
 
 
 
 
 
 
77
 
78
  except Exception as e:
79
+ error_markdown = f"# Error\n\nError processing file: {str(e)}"
80
+ return error_markdown, "", gr.Markdown(visible=True), gr.Code(visible=False)
81
 
82
  return handle_file_selection
83
 
 
89
  return gr.FileExplorer(visible=False)
90
 
91
 
92
+ def create_interface(analyzer, converter):
93
  """Create the main Gradio interface"""
94
  with gr.Blocks(title="Ada Assistant - Project Analyzer") as app:
95
  gr.Markdown("# Ada Assistant - Project Analyzer")
 
122
  with gr.Row():
123
  with gr.Column(scale=1):
124
  # Analysis results display
125
+ analysis_results = gr.Markdown(
126
  label="Business Logic Analysis",
127
+ visible=False
128
+ )
129
+
130
+ with gr.Column(scale=1):
131
+ # Python code display
132
+ python_code_display = gr.Code(
133
+ label="Converted Python Code",
134
+ language="python",
135
+ lines=20,
136
+ visible=False
137
  )
138
 
139
  # Hidden state to store extracted path
 
154
  )
155
 
156
  # Handle file selection
157
+ handle_file_selection = create_file_selection_handler(analyzer, converter)
158
  file_explorer.change(
159
  fn=handle_file_selection,
160
  inputs=[file_explorer],
161
+ outputs=[analysis_results, python_code_display, analysis_results, python_code_display]
162
  )
163
 
164
  return app
tests/test_ada_converter_agent.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tests for AdaConverterAgent."""
2
+
3
+ import unittest
4
+ from unittest.mock import Mock, patch
5
+ from src.agents.ada_converter import AdaConverterAgent
6
+
7
+
8
+ class TestAdaConverterAgent(unittest.TestCase):
9
+ """Test cases for AdaConverterAgent."""
10
+
11
+ def setUp(self):
12
+ """Set up test fixtures."""
13
+ self.mock_model = Mock()
14
+ self.agent = AdaConverterAgent(self.mock_model)
15
+
16
+ def test_initialization_with_model(self):
17
+ """Test that agent initializes correctly with a model."""
18
+ self.assertIsNotNone(self.agent)
19
+ self.assertEqual(self.agent.model, self.mock_model)
20
+
21
+ @patch('builtins.open', create=True)
22
+ @patch('src.agents.ada_converter.ToolCallingAgent')
23
+ def test_convert_to_python_with_ada_file(self, mock_tool_calling_agent, mock_open):
24
+ """Test converting Ada code to Python."""
25
+ # Setup
26
+ ada_code = """
27
+ procedure Hello is
28
+ begin
29
+ Put_Line("Hello, World!");
30
+ end Hello;
31
+ """
32
+
33
+ mock_open.return_value.__enter__.return_value.read.return_value = ada_code
34
+
35
+ # Mock the LLM response
36
+ expected_python = """
37
+ def hello():
38
+ print("Hello, World!")
39
+
40
+ if __name__ == "__main__":
41
+ hello()
42
+ """
43
+
44
+ # Mock the ToolCallingAgent response
45
+ mock_result = Mock()
46
+ mock_result.messages = [Mock(content=expected_python.strip())]
47
+ mock_tool_calling_agent.return_value.run.return_value = mock_result
48
+
49
+ # Create agent
50
+ agent = AdaConverterAgent(self.mock_model)
51
+
52
+ # Test
53
+ result = agent.convert_to_python("test_file.adb")
54
+
55
+ # Verify
56
+ self.assertIsInstance(result, str)
57
+ self.assertIn("def hello()", result)
58
+ self.assertIn('print("Hello, World!")', result)
59
+ mock_tool_calling_agent.return_value.run.assert_called_once()
60
+
61
+
62
+ if __name__ == "__main__":
63
+ unittest.main()
tests/test_code_analyzer_agent.py CHANGED
@@ -35,19 +35,39 @@ class TestCodeAnalyzerAgent:
35
  """Test extract_business_logic with Ada file path and mocked LLM response"""
36
  from unittest.mock import MagicMock
37
 
38
- # Mock the CodeAgent run method to return business logic analysis
39
  mock_result = MagicMock()
40
  mock_result.messages = []
41
  mock_message = MagicMock()
42
- mock_message.content = '''
43
- {
44
- "core_algorithms": ["TicTacToe game logic", "Board state evaluation", "Win condition checking"],
45
- "data_structures": ["Board array structure", "Position type system", "Slot enumeration"],
46
- "business_rules": ["SPARK verification contracts", "Pre/post conditions", "Game state constraints"],
47
- "domain_concepts": ["Game board management", "Player moves", "Win detection"],
48
- "conversion_complexity": "medium",
49
- "recommended_approach": "Translate to Python classes with similar structure"
50
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  '''
52
  mock_result.messages.append(mock_message)
53
 
@@ -81,19 +101,20 @@ end Tictactoe;
81
 
82
  result = analyzer_agent.extract_business_logic(ada_file)
83
 
84
- # Verify result structure
85
- assert isinstance(result, dict)
86
- assert 'core_algorithms' in result
87
- assert 'data_structures' in result
88
- assert 'business_rules' in result
89
- assert 'domain_concepts' in result
90
- assert 'conversion_complexity' in result
91
- assert 'recommended_approach' in result
 
92
 
93
  # Verify LLM found business logic concepts
94
- assert "TicTacToe game logic" in result['core_algorithms']
95
- assert "Board array structure" in result['data_structures']
96
- assert result['conversion_complexity'] == "medium"
97
 
98
  # Verify LLM analysis was called
99
  analyzer_agent.code_agent.run.assert_called_once()
 
35
  """Test extract_business_logic with Ada file path and mocked LLM response"""
36
  from unittest.mock import MagicMock
37
 
38
+ # Mock the CodeAgent run method to return markdown business logic analysis
39
  mock_result = MagicMock()
40
  mock_result.messages = []
41
  mock_message = MagicMock()
42
+ mock_message.content = '''# Business Logic Analysis
43
+
44
+ ## Core Algorithms
45
+ - TicTacToe game logic
46
+ - Board state evaluation
47
+ - Win condition checking
48
+
49
+ ## Data Structures & Types
50
+ - Board array structure
51
+ - Position type system
52
+ - Slot enumeration
53
+
54
+ ## Business Rules & Constraints
55
+ - SPARK verification contracts
56
+ - Pre/post conditions
57
+ - Game state constraints
58
+
59
+ ## Domain Concepts
60
+ - Game board management
61
+ - Player moves
62
+ - Win detection
63
+
64
+ ## Conversion Complexity
65
+ **Level**: Medium
66
+
67
+ **Reasoning**: Moderate complexity due to formal verification contracts
68
+
69
+ ## Recommended Approach
70
+ Translate to Python classes with similar structure
71
  '''
72
  mock_result.messages.append(mock_message)
73
 
 
101
 
102
  result = analyzer_agent.extract_business_logic(ada_file)
103
 
104
+ # Verify result is markdown string
105
+ assert isinstance(result, str)
106
+ assert "# Business Logic Analysis" in result
107
+ assert "## Core Algorithms" in result
108
+ assert "## Data Structures & Types" in result
109
+ assert "## Business Rules & Constraints" in result
110
+ assert "## Domain Concepts" in result
111
+ assert "## Conversion Complexity" in result
112
+ assert "## Recommended Approach" in result
113
 
114
  # Verify LLM found business logic concepts
115
+ assert "TicTacToe game logic" in result
116
+ assert "Board array structure" in result
117
+ assert "Medium" in result
118
 
119
  # Verify LLM analysis was called
120
  analyzer_agent.code_agent.run.assert_called_once()