algomath-extract 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +260 -0
  2. package/bin/algo-extract.js +143 -0
  3. package/bin/algo-generate.js +102 -0
  4. package/bin/algo-help.js +136 -0
  5. package/bin/algo-list.js +56 -0
  6. package/bin/algo-run.js +141 -0
  7. package/bin/algo-status.js +88 -0
  8. package/bin/algo-verify.js +189 -0
  9. package/bin/install.js +349 -0
  10. package/package.json +57 -0
  11. package/requirements.txt +20 -0
  12. package/src/__pycache__/intent.cpython-313.pyc +0 -0
  13. package/src/cli/__pycache__/commands.cpython-313.pyc +0 -0
  14. package/src/cli/cli_entry.py +106 -0
  15. package/src/cli/commands.py +339 -0
  16. package/src/execution/__init__.py +74 -0
  17. package/src/execution/__pycache__/__init__.cpython-313.pyc +0 -0
  18. package/src/execution/__pycache__/display.cpython-313.pyc +0 -0
  19. package/src/execution/__pycache__/errors.cpython-313.pyc +0 -0
  20. package/src/execution/__pycache__/executor.cpython-313.pyc +0 -0
  21. package/src/execution/__pycache__/sandbox.cpython-313.pyc +0 -0
  22. package/src/execution/display.py +261 -0
  23. package/src/execution/errors.py +158 -0
  24. package/src/execution/executor.py +253 -0
  25. package/src/execution/sandbox.py +333 -0
  26. package/src/extraction/__init__.py +102 -0
  27. package/src/extraction/__pycache__/__init__.cpython-313.pyc +0 -0
  28. package/src/extraction/__pycache__/boundaries.cpython-313.pyc +0 -0
  29. package/src/extraction/__pycache__/errors.cpython-313.pyc +0 -0
  30. package/src/extraction/__pycache__/llm_extraction.cpython-313.pyc +0 -0
  31. package/src/extraction/__pycache__/notation.cpython-313.pyc +0 -0
  32. package/src/extraction/__pycache__/parser.cpython-313.pyc +0 -0
  33. package/src/extraction/__pycache__/pdf_processor.cpython-313.pyc +0 -0
  34. package/src/extraction/__pycache__/prompts.cpython-313.pyc +0 -0
  35. package/src/extraction/__pycache__/review.cpython-313.pyc +0 -0
  36. package/src/extraction/__pycache__/schema.cpython-313.pyc +0 -0
  37. package/src/extraction/__pycache__/validation.cpython-313.pyc +0 -0
  38. package/src/extraction/boundaries.py +281 -0
  39. package/src/extraction/errors.py +156 -0
  40. package/src/extraction/llm_extraction.py +225 -0
  41. package/src/extraction/notation.py +240 -0
  42. package/src/extraction/parser.py +402 -0
  43. package/src/extraction/pdf_processor.py +281 -0
  44. package/src/extraction/prompts.py +90 -0
  45. package/src/extraction/review.py +298 -0
  46. package/src/extraction/schema.py +173 -0
  47. package/src/extraction/validation.py +202 -0
  48. package/src/generation/__init__.py +79 -0
  49. package/src/generation/__pycache__/__init__.cpython-313.pyc +0 -0
  50. package/src/generation/__pycache__/code_generator.cpython-313.pyc +0 -0
  51. package/src/generation/__pycache__/errors.cpython-313.pyc +0 -0
  52. package/src/generation/__pycache__/hybrid.cpython-313.pyc +0 -0
  53. package/src/generation/__pycache__/llm_generator.cpython-313.pyc +0 -0
  54. package/src/generation/__pycache__/persistence.cpython-313.pyc +0 -0
  55. package/src/generation/__pycache__/prompts.cpython-313.pyc +0 -0
  56. package/src/generation/__pycache__/review.cpython-313.pyc +0 -0
  57. package/src/generation/__pycache__/templates.cpython-313.pyc +0 -0
  58. package/src/generation/__pycache__/types.cpython-313.pyc +0 -0
  59. package/src/generation/__pycache__/validation.cpython-313.pyc +0 -0
  60. package/src/generation/code_generator.py +375 -0
  61. package/src/generation/errors.py +84 -0
  62. package/src/generation/hybrid.py +210 -0
  63. package/src/generation/llm_generator.py +223 -0
  64. package/src/generation/persistence.py +221 -0
  65. package/src/generation/prompts.py +202 -0
  66. package/src/generation/review.py +254 -0
  67. package/src/generation/templates.py +208 -0
  68. package/src/generation/types.py +196 -0
  69. package/src/generation/validation.py +278 -0
  70. package/src/intent.py +323 -0
  71. package/src/verification/__init__.py +63 -0
  72. package/src/verification/__pycache__/__init__.cpython-313.pyc +0 -0
  73. package/src/verification/__pycache__/checker.cpython-313.pyc +0 -0
  74. package/src/verification/__pycache__/comparison.cpython-313.pyc +0 -0
  75. package/src/verification/__pycache__/explainer.cpython-313.pyc +0 -0
  76. package/src/verification/__pycache__/static_analysis.cpython-313.pyc +0 -0
  77. package/src/verification/checker.py +220 -0
  78. package/src/verification/comparison.py +492 -0
  79. package/src/verification/explainer.py +414 -0
  80. package/src/verification/static_analysis.py +540 -0
  81. package/src/workflows/__init__.py +21 -0
  82. package/src/workflows/__pycache__/__init__.cpython-313.pyc +0 -0
  83. package/src/workflows/__pycache__/extract.cpython-313.pyc +0 -0
  84. package/src/workflows/__pycache__/generate.cpython-313.pyc +0 -0
  85. package/src/workflows/__pycache__/run.cpython-313.pyc +0 -0
  86. package/src/workflows/__pycache__/verify.cpython-313.pyc +0 -0
  87. package/src/workflows/extract.py +181 -0
  88. package/src/workflows/generate.py +155 -0
  89. package/src/workflows/run.py +187 -0
  90. package/src/workflows/verify.py +334 -0
@@ -0,0 +1,278 @@
1
+ """Code validation utilities.
2
+
3
+ This module provides validation for generated Python code.
4
+ """
5
+
6
+ import ast
7
+ import importlib.util
8
+ import re
9
+ import subprocess
10
+ import tempfile
11
+ import os
12
+ from dataclasses import dataclass, field
13
+ from typing import Any, Dict, List, Optional
14
+
15
+ from src.generation.errors import GenerationError, SyntaxGenerationError
16
+
17
+
18
+ @dataclass
19
+ class ValidationResult:
20
+ """
21
+ Represents validation results.
22
+
23
+ Attributes:
24
+ is_valid: Whether validation passed
25
+ errors: List of error dictionaries
26
+ warnings: List of warning messages
27
+ """
28
+ is_valid: bool
29
+ errors: List[Dict[str, Any]] = field(default_factory=list)
30
+ warnings: List[str] = field(default_factory=list)
31
+
32
+ @property
33
+ def has_errors(self) -> bool:
34
+ return len(self.errors) > 0
35
+
36
+ @property
37
+ def error_count(self) -> int:
38
+ return len(self.errors)
39
+
40
+
41
+ class CodeValidator:
42
+ """
43
+ Validate generated Python code.
44
+
45
+ Provides syntax, import, and optional runtime validation.
46
+ """
47
+
48
+ def __init__(self, check_runtime: bool = False):
49
+ """
50
+ Initialize validator.
51
+
52
+ Args:
53
+ check_runtime: Whether to run runtime checks
54
+ """
55
+ self.check_runtime = check_runtime
56
+ self.errors = []
57
+
58
+ def validate(self, code: str) -> ValidationResult:
59
+ """
60
+ Run all validation checks.
61
+
62
+ Args:
63
+ code: Python code to validate
64
+
65
+ Returns:
66
+ ValidationResult with errors and warnings
67
+ """
68
+ results = []
69
+
70
+ # Syntax validation
71
+ results.append(self.validate_syntax(code))
72
+
73
+ # Import validation
74
+ results.append(self.validate_imports(code))
75
+
76
+ # Runtime check if enabled
77
+ if self.check_runtime:
78
+ results.append(self.validate_runtime(code))
79
+
80
+ # Merge results
81
+ all_errors = []
82
+ all_warnings = []
83
+ for r in results:
84
+ all_errors.extend(r.errors)
85
+ all_warnings.extend(r.warnings)
86
+
87
+ return ValidationResult(
88
+ is_valid=len(all_errors) == 0,
89
+ errors=all_errors,
90
+ warnings=all_warnings
91
+ )
92
+
93
+ def validate_syntax(self, code: str) -> ValidationResult:
94
+ """
95
+ Validate Python syntax using ast module.
96
+
97
+ Args:
98
+ code: Python code to validate
99
+
100
+ Returns:
101
+ ValidationResult
102
+ """
103
+ try:
104
+ ast.parse(code)
105
+ return ValidationResult(is_valid=True, errors=[], warnings=[])
106
+ except SyntaxError as e:
107
+ error = {
108
+ 'message': f"Syntax error: {e.msg}",
109
+ 'line': e.lineno,
110
+ 'type': 'syntax',
111
+ 'text': e.text
112
+ }
113
+ return ValidationResult(
114
+ is_valid=False,
115
+ errors=[error],
116
+ warnings=[]
117
+ )
118
+
119
+ def validate_imports(self, code: str) -> ValidationResult:
120
+ """
121
+ Verify imports can be resolved.
122
+
123
+ Args:
124
+ code: Python code to validate
125
+
126
+ Returns:
127
+ ValidationResult
128
+ """
129
+ try:
130
+ tree = ast.parse(code)
131
+ except SyntaxError:
132
+ return ValidationResult(is_valid=False, errors=[], warnings=[])
133
+
134
+ errors = []
135
+ warnings = []
136
+
137
+ for node in ast.walk(tree):
138
+ if isinstance(node, ast.Import):
139
+ for alias in node.names:
140
+ if not self._can_import(alias.name.split('.')[0]):
141
+ errors.append({
142
+ 'message': f"Cannot import module: {alias.name}",
143
+ 'line': node.lineno,
144
+ 'type': 'import'
145
+ })
146
+ elif isinstance(node, ast.ImportFrom):
147
+ if node.module:
148
+ if not self._can_import(node.module.split('.')[0]):
149
+ errors.append({
150
+ 'message': f"Cannot import module: {node.module}",
151
+ 'line': node.lineno,
152
+ 'type': 'import'
153
+ })
154
+
155
+ return ValidationResult(
156
+ is_valid=len(errors) == 0,
157
+ errors=errors,
158
+ warnings=warnings
159
+ )
160
+
161
+ def _can_import(self, module_name: str) -> bool:
162
+ """
163
+ Check if module can be imported.
164
+
165
+ Args:
166
+ module_name: Module name to check
167
+
168
+ Returns:
169
+ True if module can be imported
170
+ """
171
+ # Built-in modules that don't need checking
172
+ built_ins = {'builtins', 'types', 'typing', 'abc', 'collections'}
173
+ if module_name in built_ins:
174
+ return True
175
+
176
+ try:
177
+ return importlib.util.find_spec(module_name) is not None
178
+ except (ImportError, ModuleNotFoundError):
179
+ return False
180
+
181
+ def validate_runtime(self, code: str, timeout: int = 5) -> ValidationResult:
182
+ """
183
+ Execute code in sandbox to check for NameError.
184
+
185
+ Args:
186
+ code: Python code to validate
187
+ timeout: Timeout in seconds
188
+
189
+ Returns:
190
+ ValidationResult
191
+ """
192
+ # Create temp file
193
+ with tempfile.NamedTemporaryFile(
194
+ mode='w',
195
+ suffix='.py',
196
+ delete=False
197
+ ) as f:
198
+ f.write(code)
199
+ temp_path = f.name
200
+
201
+ try:
202
+ # Run with timeout
203
+ result = subprocess.run(
204
+ ['python', temp_path],
205
+ capture_output=True,
206
+ text=True,
207
+ timeout=timeout
208
+ )
209
+
210
+ errors = []
211
+ if result.returncode != 0:
212
+ if 'NameError' in result.stderr:
213
+ errors.append({
214
+ 'message': f"NameError: {result.stderr}",
215
+ 'line': self._extract_line_from_traceback(result.stderr),
216
+ 'type': 'runtime'
217
+ })
218
+ elif 'SyntaxError' not in result.stderr:
219
+ errors.append({
220
+ 'message': f"Runtime error: {result.stderr}",
221
+ 'line': None,
222
+ 'type': 'runtime'
223
+ })
224
+
225
+ return ValidationResult(
226
+ is_valid=len(errors) == 0,
227
+ errors=errors,
228
+ warnings=[]
229
+ )
230
+
231
+ except subprocess.TimeoutExpired:
232
+ return ValidationResult(
233
+ is_valid=False,
234
+ errors=[{
235
+ 'message': f'Runtime validation timed out after {timeout}s',
236
+ 'line': None,
237
+ 'type': 'timeout'
238
+ }],
239
+ warnings=[]
240
+ )
241
+ finally:
242
+ os.unlink(temp_path)
243
+
244
+ def _extract_line_from_traceback(self, stderr: str) -> Optional[int]:
245
+ """
246
+ Extract line number from traceback.
247
+
248
+ Args:
249
+ stderr: Stderr text from subprocess
250
+
251
+ Returns:
252
+ Line number or None
253
+ """
254
+ match = re.search(r'line (\d+)', stderr)
255
+ if match:
256
+ return int(match.group(1))
257
+ return None
258
+
259
+
260
+ def validate_generated(generated_code: Any) -> ValidationResult:
261
+ """
262
+ Validate a GeneratedCode object.
263
+
264
+ Args:
265
+ generated_code: GeneratedCode object to validate
266
+
267
+ Returns:
268
+ ValidationResult
269
+ """
270
+ validator = CodeValidator()
271
+ return validator.validate(generated_code.source)
272
+
273
+
274
+ __all__ = [
275
+ 'ValidationResult',
276
+ 'CodeValidator',
277
+ 'validate_generated',
278
+ ]
package/src/intent.py ADDED
@@ -0,0 +1,323 @@
1
+ """
2
+ Intent detection and routing for AlgoMath.
3
+
4
+ This module provides natural language intent detection and workflow routing,
5
+ enabling users to interact with the system using conversational language.
6
+ """
7
+
8
+ from enum import Enum, auto
9
+ from typing import Tuple, List, Dict, Optional
10
+ import re
11
+
12
+
13
+ class IntentType(Enum):
14
+ """Enumeration of supported user intents."""
15
+ EXTRACT = auto() # Extract algorithm from text
16
+ GENERATE = auto() # Generate code from steps
17
+ RUN = auto() # Execute generated code
18
+ VERIFY = auto() # Verify execution results
19
+ STATUS = auto() # Check current state
20
+ LIST = auto() # List algorithms
21
+ HELP = auto() # Show help
22
+ UNKNOWN = auto() # Could not determine intent
23
+
24
+
25
+ # Keyword mappings for intent detection
26
+ INTENT_KEYWORDS: Dict[IntentType, List[str]] = {
27
+ IntentType.EXTRACT: [
28
+ "extract", "parse", "get steps", "analyze text", "pull out",
29
+ "find algorithm", "identify", "get algorithm", "from text",
30
+ "steps from", "parse this", "analyze", "read", "interpret"
31
+ ],
32
+ IntentType.GENERATE: [
33
+ "generate", "create code", "write python", "implement",
34
+ "code this", "make code", "turn into code", "convert to code",
35
+ "python code", "write code", "produce code", "build code"
36
+ ],
37
+ IntentType.RUN: [
38
+ "run", "execute", "execute code", "test", "run code",
39
+ "run it", "execute it", "try it", "run the", "execute the",
40
+ "run algorithm", "execute algorithm", "test code", "try code"
41
+ ],
42
+ IntentType.VERIFY: [
43
+ "verify", "check", "validate", "explain", "confirm",
44
+ "is this correct", "does this work", "validate results",
45
+ "check output", "verify results", "explain why", "how does this work"
46
+ ],
47
+ IntentType.STATUS: [
48
+ "status", "state", "progress", "where am i", "what's next",
49
+ "current state", "show status", "check status", "where are we",
50
+ "what step", "what phase", "how far", "progress so far"
51
+ ],
52
+ IntentType.LIST: [
53
+ "list", "show algorithms", "what do i have", "saved algorithms",
54
+ "my algorithms", "view algorithms", "list algorithms", "show all",
55
+ "what algorithms", "saved", "previous algorithms"
56
+ ],
57
+ IntentType.HELP: [
58
+ "help", "how to", "what can you do", "commands", "how do i",
59
+ "show help", "list commands", "usage", "instructions",
60
+ "what commands", "available commands", "command list"
61
+ ],
62
+ }
63
+
64
+
65
+ def _calculate_confidence(user_input: str, keywords: List[str]) -> float:
66
+ """
67
+ Calculate confidence score based on keyword matches.
68
+
69
+ Args:
70
+ user_input: The user's input text (lowercased)
71
+ keywords: List of keywords for this intent
72
+
73
+ Returns:
74
+ float: Confidence score between 0.0 and 1.0
75
+ """
76
+ if not user_input or not keywords:
77
+ return 0.0
78
+
79
+ matches = 0
80
+ matched_phrases = []
81
+
82
+ for keyword in keywords:
83
+ if keyword in user_input:
84
+ # Phrase matches get higher weight
85
+ if len(keyword.split()) > 1:
86
+ matches += 2.0
87
+ else:
88
+ matches += 1.0
89
+ matched_phrases.append(keyword)
90
+
91
+ if matches == 0:
92
+ return 0.0
93
+
94
+ # Confidence based on number of matches relative to keyword list
95
+ # and weighted by phrase matches
96
+ base_confidence = matches / (len(keywords) * 0.3)
97
+
98
+ # Boost confidence for direct phrase matches
99
+ if any(phrase in user_input for phrase in matched_phrases if len(phrase.split()) > 1):
100
+ base_confidence = min(base_confidence * 1.3, 1.0)
101
+
102
+ return min(base_confidence, 1.0)
103
+
104
+
105
+ def detect_intent(user_input: str) -> Tuple[IntentType, float]:
106
+ """
107
+ Detect user intent from natural language input.
108
+
109
+ Uses keyword matching to classify the user's intent and returns
110
+ both the intent type and a confidence score.
111
+
112
+ Args:
113
+ user_input: The natural language input from the user
114
+
115
+ Returns:
116
+ Tuple of (IntentType, confidence_score)
117
+ confidence_score is between 0.0 and 1.0
118
+
119
+ Examples:
120
+ >>> detect_intent("extract the algorithm from this text")
121
+ (IntentType.EXTRACT, 0.85)
122
+
123
+ >>> detect_intent("generate code for this")
124
+ (IntentType.GENERATE, 0.92)
125
+
126
+ >>> detect_intent("run it")
127
+ (IntentType.RUN, 0.45) # Low confidence - needs context
128
+
129
+ >>> detect_intent("can you help me")
130
+ (IntentType.HELP, 0.90)
131
+ """
132
+ if not user_input or not isinstance(user_input, str):
133
+ return IntentType.UNKNOWN, 0.0
134
+
135
+ normalized = user_input.lower().strip()
136
+
137
+ # Remove punctuation for matching
138
+ normalized = re.sub(r'[^\w\s]', ' ', normalized)
139
+ normalized = re.sub(r'\s+', ' ', normalized).strip()
140
+
141
+ scores: Dict[IntentType, float] = {}
142
+
143
+ for intent_type, keywords in INTENT_KEYWORDS.items():
144
+ if intent_type == IntentType.UNKNOWN:
145
+ continue
146
+ scores[intent_type] = _calculate_confidence(normalized, keywords)
147
+
148
+ # Find highest scoring intent
149
+ if not scores:
150
+ return IntentType.UNKNOWN, 0.0
151
+
152
+ best_intent = max(scores, key=scores.get)
153
+ best_score = scores[best_intent]
154
+
155
+ # Check for ambiguity (multiple high scores)
156
+ high_scores = [s for s in scores.values() if s > 0.5]
157
+ if len(high_scores) > 1:
158
+ # Reduce confidence if multiple intents match
159
+ best_score *= 0.8
160
+
161
+ # Unknown if below threshold
162
+ if best_score < 0.2:
163
+ return IntentType.UNKNOWN, best_score
164
+
165
+ return best_intent, round(best_score, 2)
166
+
167
+
168
+ def route_to_workflow(intent: IntentType) -> Optional[str]:
169
+ """
170
+ Return the workflow module path for the given intent.
171
+
172
+ Maps detected intents to their corresponding workflow modules.
173
+
174
+ Args:
175
+ intent: The detected intent type
176
+
177
+ Returns:
178
+ Module path string or None if no workflow exists
179
+
180
+ Examples:
181
+ >>> route_to_workflow(IntentType.EXTRACT)
182
+ 'src.workflows.extract'
183
+
184
+ >>> route_to_workflow(IntentType.UNKNOWN)
185
+ None
186
+ """
187
+ workflow_map: Dict[IntentType, Optional[str]] = {
188
+ IntentType.EXTRACT: 'src.workflows.extract',
189
+ IntentType.GENERATE: 'src.workflows.generate',
190
+ IntentType.RUN: 'src.workflows.run',
191
+ IntentType.VERIFY: 'src.workflows.verify',
192
+ IntentType.STATUS: None, # Handled by context directly
193
+ IntentType.LIST: None, # Handled by context directly
194
+ IntentType.HELP: None, # Handled by command system
195
+ IntentType.UNKNOWN: None,
196
+ }
197
+
198
+ return workflow_map.get(intent)
199
+
200
+
201
+ def suggest_next_steps(current_state: str) -> List[str]:
202
+ """
203
+ Suggest next actions based on current workflow state.
204
+
205
+ Provides context-aware recommendations for what the user can do next.
206
+
207
+ Args:
208
+ current_state: Current state identifier (e.g., 'TEXT_EXTRACTED',
209
+ 'CODE_GENERATED', 'EXECUTION_COMPLETE', etc.)
210
+
211
+ Returns:
212
+ List of actionable suggestions
213
+
214
+ Examples:
215
+ >>> suggest_next_steps('TEXT_EXTRACTED')
216
+ ['Generate code with /algo-generate', 'Edit extracted text', 'Start over with /algo-extract']
217
+
218
+ >>> suggest_next_steps('CODE_GENERATED')
219
+ ['Run the code with /algo-run', 'Review code before running', 'Regenerate if needed']
220
+
221
+ >>> suggest_next_steps('EXECUTION_COMPLETE')
222
+ ['Verify results with /algo-verify', 'Run with different inputs', 'Modify and regenerate']
223
+ """
224
+ if not current_state:
225
+ return [
226
+ "Extract an algorithm with /algo-extract",
227
+ "List saved algorithms with /algo-list",
228
+ "Show help with /algo-help"
229
+ ]
230
+
231
+ suggestions: Dict[str, List[str]] = {
232
+ 'NO_SESSION': [
233
+ "Start by extracting an algorithm: /algo-extract",
234
+ "Or load a saved algorithm: /algo-extract [name]",
235
+ "See all commands: /algo-help"
236
+ ],
237
+ 'TEXT_SAVED': [
238
+ "Extract steps from the text: /algo-extract (auto-detects)",
239
+ "View current text: /algo-status",
240
+ "Start over: /algo-extract"
241
+ ],
242
+ 'TEXT_EXTRACTED': [
243
+ "Generate code with /algo-generate",
244
+ "Review extracted steps: /algo-status",
245
+ "Edit the algorithm text",
246
+ "Extract a different algorithm: /algo-extract"
247
+ ],
248
+ 'STEPS_STRUCTURED': [
249
+ "Generate Python code: /algo-generate",
250
+ "Review structured steps: /algo-status",
251
+ "Go back and edit: /algo-extract",
252
+ "View all saved: /algo-list"
253
+ ],
254
+ 'CODE_GENERATED': [
255
+ "Run the code: /algo-run",
256
+ "Review code before running: /algo-verify",
257
+ "Regenerate if needed: /algo-generate",
258
+ "Check current status: /algo-status"
259
+ ],
260
+ 'CODE_SAVED': [
261
+ "Execute the code: /algo-run",
262
+ "Run with specific input: /algo-run [input]",
263
+ "Review the code: /algo-status"
264
+ ],
265
+ 'EXECUTION_COMPLETE': [
266
+ "Verify results: /algo-verify",
267
+ "Run with different inputs: /algo-run",
268
+ "Check execution details: /algo-status",
269
+ "Start new algorithm: /algo-extract"
270
+ ],
271
+ 'EXECUTION_FAILED': [
272
+ "Review the error: /algo-status",
273
+ "Regenerate code: /algo-generate",
274
+ "Check inputs and try again: /algo-run",
275
+ "Verify code logic: /algo-verify"
276
+ ],
277
+ 'VERIFICATION_COMPLETE': [
278
+ "Extract another algorithm: /algo-extract",
279
+ "List all saved algorithms: /algo-list",
280
+ "Start fresh: /algo-extract"
281
+ ],
282
+ 'DEFAULT': [
283
+ "Check current status: /algo-status",
284
+ "Show available commands: /algo-help",
285
+ "List saved algorithms: /algo-list"
286
+ ]
287
+ }
288
+
289
+ return suggestions.get(current_state, suggestions['DEFAULT'])
290
+
291
+
292
+ def get_intent_description(intent: IntentType) -> str:
293
+ """
294
+ Get a human-readable description of an intent type.
295
+
296
+ Args:
297
+ intent: The intent type
298
+
299
+ Returns:
300
+ Description string
301
+ """
302
+ descriptions: Dict[IntentType, str] = {
303
+ IntentType.EXTRACT: "Extract algorithm from mathematical text",
304
+ IntentType.GENERATE: "Generate executable code from algorithm steps",
305
+ IntentType.RUN: "Execute generated code",
306
+ IntentType.VERIFY: "Verify execution results and explain behavior",
307
+ IntentType.STATUS: "Show current algorithm state and progress",
308
+ IntentType.LIST: "List all saved algorithms",
309
+ IntentType.HELP: "Show help and available commands",
310
+ IntentType.UNKNOWN: "Unknown intent - could not determine",
311
+ }
312
+ return descriptions.get(intent, "Unknown")
313
+
314
+
315
+ # Exports
316
+ __all__ = [
317
+ 'IntentType',
318
+ 'detect_intent',
319
+ 'route_to_workflow',
320
+ 'suggest_next_steps',
321
+ 'get_intent_description',
322
+ 'INTENT_KEYWORDS',
323
+ ]
@@ -0,0 +1,63 @@
1
+ """Verification module for AlgoMath.
2
+
3
+ Provides execution verification, comparison, explanation, and edge case detection.
4
+ """
5
+
6
+ # From checker.py (existing)
7
+ from .checker import (
8
+ ExecutionChecker,
9
+ VerificationResult,
10
+ VerificationStatus,
11
+ verify_execution,
12
+ )
13
+
14
+ # From comparison.py (existing)
15
+ from .comparison import (
16
+ ComparisonResult,
17
+ ComparisonStatus,
18
+ OutputComparator,
19
+ compare_outputs,
20
+ prompt_for_expected,
21
+ )
22
+
23
+ # From explainer.py (new)
24
+ from .explainer import (
25
+ AlgorithmExplainer,
26
+ ExplanationResult,
27
+ ExplanationLevel,
28
+ StepExplanation,
29
+ explain_algorithm,
30
+ )
31
+
32
+ # From static_analysis.py (new)
33
+ from .static_analysis import (
34
+ EdgeCaseDetector,
35
+ EdgeCase,
36
+ EdgeCaseSeverity,
37
+ detect_edge_cases,
38
+ )
39
+
40
+ __all__ = [
41
+ # Checker
42
+ 'ExecutionChecker',
43
+ 'VerificationResult',
44
+ 'VerificationStatus',
45
+ 'verify_execution',
46
+ # Comparison
47
+ 'ComparisonResult',
48
+ 'ComparisonStatus',
49
+ 'OutputComparator',
50
+ 'compare_outputs',
51
+ 'prompt_for_expected',
52
+ # Explainer
53
+ 'AlgorithmExplainer',
54
+ 'ExplanationResult',
55
+ 'ExplanationLevel',
56
+ 'StepExplanation',
57
+ 'explain_algorithm',
58
+ # Edge Case Detection
59
+ 'EdgeCaseDetector',
60
+ 'EdgeCase',
61
+ 'EdgeCaseSeverity',
62
+ 'detect_edge_cases',
63
+ ]