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.
- package/README.md +260 -0
- package/bin/algo-extract.js +143 -0
- package/bin/algo-generate.js +102 -0
- package/bin/algo-help.js +136 -0
- package/bin/algo-list.js +56 -0
- package/bin/algo-run.js +141 -0
- package/bin/algo-status.js +88 -0
- package/bin/algo-verify.js +189 -0
- package/bin/install.js +349 -0
- package/package.json +57 -0
- package/requirements.txt +20 -0
- package/src/__pycache__/intent.cpython-313.pyc +0 -0
- package/src/cli/__pycache__/commands.cpython-313.pyc +0 -0
- package/src/cli/cli_entry.py +106 -0
- package/src/cli/commands.py +339 -0
- package/src/execution/__init__.py +74 -0
- package/src/execution/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/execution/__pycache__/display.cpython-313.pyc +0 -0
- package/src/execution/__pycache__/errors.cpython-313.pyc +0 -0
- package/src/execution/__pycache__/executor.cpython-313.pyc +0 -0
- package/src/execution/__pycache__/sandbox.cpython-313.pyc +0 -0
- package/src/execution/display.py +261 -0
- package/src/execution/errors.py +158 -0
- package/src/execution/executor.py +253 -0
- package/src/execution/sandbox.py +333 -0
- package/src/extraction/__init__.py +102 -0
- package/src/extraction/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/boundaries.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/errors.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/llm_extraction.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/notation.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/parser.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/pdf_processor.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/prompts.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/review.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/schema.cpython-313.pyc +0 -0
- package/src/extraction/__pycache__/validation.cpython-313.pyc +0 -0
- package/src/extraction/boundaries.py +281 -0
- package/src/extraction/errors.py +156 -0
- package/src/extraction/llm_extraction.py +225 -0
- package/src/extraction/notation.py +240 -0
- package/src/extraction/parser.py +402 -0
- package/src/extraction/pdf_processor.py +281 -0
- package/src/extraction/prompts.py +90 -0
- package/src/extraction/review.py +298 -0
- package/src/extraction/schema.py +173 -0
- package/src/extraction/validation.py +202 -0
- package/src/generation/__init__.py +79 -0
- package/src/generation/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/code_generator.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/errors.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/hybrid.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/llm_generator.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/persistence.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/prompts.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/review.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/templates.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/types.cpython-313.pyc +0 -0
- package/src/generation/__pycache__/validation.cpython-313.pyc +0 -0
- package/src/generation/code_generator.py +375 -0
- package/src/generation/errors.py +84 -0
- package/src/generation/hybrid.py +210 -0
- package/src/generation/llm_generator.py +223 -0
- package/src/generation/persistence.py +221 -0
- package/src/generation/prompts.py +202 -0
- package/src/generation/review.py +254 -0
- package/src/generation/templates.py +208 -0
- package/src/generation/types.py +196 -0
- package/src/generation/validation.py +278 -0
- package/src/intent.py +323 -0
- package/src/verification/__init__.py +63 -0
- package/src/verification/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/verification/__pycache__/checker.cpython-313.pyc +0 -0
- package/src/verification/__pycache__/comparison.cpython-313.pyc +0 -0
- package/src/verification/__pycache__/explainer.cpython-313.pyc +0 -0
- package/src/verification/__pycache__/static_analysis.cpython-313.pyc +0 -0
- package/src/verification/checker.py +220 -0
- package/src/verification/comparison.py +492 -0
- package/src/verification/explainer.py +414 -0
- package/src/verification/static_analysis.py +540 -0
- package/src/workflows/__init__.py +21 -0
- package/src/workflows/__pycache__/__init__.cpython-313.pyc +0 -0
- package/src/workflows/__pycache__/extract.cpython-313.pyc +0 -0
- package/src/workflows/__pycache__/generate.cpython-313.pyc +0 -0
- package/src/workflows/__pycache__/run.cpython-313.pyc +0 -0
- package/src/workflows/__pycache__/verify.cpython-313.pyc +0 -0
- package/src/workflows/extract.py +181 -0
- package/src/workflows/generate.py +155 -0
- package/src/workflows/run.py +187 -0
- package/src/workflows/verify.py +334 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""Extraction workflow for AlgoMath."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, List, Optional, Any
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
# Add project root to Python path
|
|
8
|
+
project_root = Path(__file__).parent.parent.parent
|
|
9
|
+
if str(project_root) not in sys.path:
|
|
10
|
+
sys.path.insert(0, str(project_root))
|
|
11
|
+
|
|
12
|
+
# Import extraction components
|
|
13
|
+
from src.extraction.llm_extraction import HybridExtractor
|
|
14
|
+
from src.extraction.review import ReviewInterface
|
|
15
|
+
from src.extraction.schema import algorithm_to_json
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def show_progress(phase: str, current: int, total: int) -> str:
|
|
19
|
+
"""
|
|
20
|
+
Generate a progress bar string.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
phase: Name of the current phase
|
|
24
|
+
current: Current step number
|
|
25
|
+
total: Total number of steps
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Formatted progress bar string
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
>>> show_progress("Extract", 8, 10)
|
|
32
|
+
"Extract: ████████░░ 80%"
|
|
33
|
+
"""
|
|
34
|
+
if total <= 0:
|
|
35
|
+
return f"{phase}: ░░░░░░░░░░ 0%"
|
|
36
|
+
|
|
37
|
+
filled = int(10 * current / total)
|
|
38
|
+
filled = max(0, min(filled, 10)) # Clamp to 0-10 range
|
|
39
|
+
bar = '█' * filled + '░' * (10 - filled)
|
|
40
|
+
pct = int(100 * current / total)
|
|
41
|
+
return f"{phase}: {bar} {pct}%"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def run_extraction(
|
|
45
|
+
context: Any,
|
|
46
|
+
text: Optional[str] = None,
|
|
47
|
+
name: Optional[str] = None,
|
|
48
|
+
skip_review: bool = False
|
|
49
|
+
) -> Dict[str, Any]:
|
|
50
|
+
"""
|
|
51
|
+
Run the extraction workflow with hybrid extraction.
|
|
52
|
+
|
|
53
|
+
Per EXT-01, EXT-02, EXT-03, EXT-04, EXT-05, EXT-06.
|
|
54
|
+
"""
|
|
55
|
+
# Import here to avoid circular imports
|
|
56
|
+
from algomath.context import ContextManager
|
|
57
|
+
from algomath.state import WorkflowState
|
|
58
|
+
|
|
59
|
+
# Progress: Parsing
|
|
60
|
+
progress = show_progress("Extract", 1, 5)
|
|
61
|
+
|
|
62
|
+
# Check if we have algorithm text
|
|
63
|
+
if text is None:
|
|
64
|
+
return {
|
|
65
|
+
'status': 'needs_input',
|
|
66
|
+
'progress': progress,
|
|
67
|
+
'message': 'Please provide algorithm text to extract',
|
|
68
|
+
'next_steps': [
|
|
69
|
+
'Provide algorithm text',
|
|
70
|
+
'Cancel extraction'
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# Save text to context
|
|
75
|
+
context.save_text(text)
|
|
76
|
+
|
|
77
|
+
# Progress: Extracting
|
|
78
|
+
progress = show_progress("Extract", 2, 5)
|
|
79
|
+
|
|
80
|
+
# Run hybrid extraction
|
|
81
|
+
extractor = HybridExtractor()
|
|
82
|
+
result = extractor.extract(text, prefer_llm=True)
|
|
83
|
+
|
|
84
|
+
if not result.success:
|
|
85
|
+
return {
|
|
86
|
+
'status': 'extraction_failed',
|
|
87
|
+
'progress': progress,
|
|
88
|
+
'errors': result.errors,
|
|
89
|
+
'message': 'Failed to extract algorithm from text',
|
|
90
|
+
'next_steps': [
|
|
91
|
+
'Try again with clearer text',
|
|
92
|
+
'Cancel extraction'
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# Progress: Structuring
|
|
97
|
+
progress = show_progress("Extract", 3, 5)
|
|
98
|
+
|
|
99
|
+
# Convert steps to JSON-serializable format
|
|
100
|
+
algorithm = result.algorithm
|
|
101
|
+
steps_data = []
|
|
102
|
+
for step in algorithm.steps:
|
|
103
|
+
steps_data.append({
|
|
104
|
+
'id': step.id,
|
|
105
|
+
'type': step.type.value,
|
|
106
|
+
'description': step.description,
|
|
107
|
+
'inputs': step.inputs,
|
|
108
|
+
'outputs': step.outputs,
|
|
109
|
+
'line_refs': step.line_refs,
|
|
110
|
+
'condition': step.condition,
|
|
111
|
+
'body': step.body,
|
|
112
|
+
'else_body': step.else_body,
|
|
113
|
+
'iter_var': step.iter_var,
|
|
114
|
+
'iter_range': step.iter_range,
|
|
115
|
+
'expression': step.expression,
|
|
116
|
+
'call_target': step.call_target,
|
|
117
|
+
'arguments': step.arguments,
|
|
118
|
+
'annotation': step.annotation
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
# Prepare review interface
|
|
122
|
+
review = ReviewInterface(algorithm)
|
|
123
|
+
|
|
124
|
+
# Progress: Validating
|
|
125
|
+
progress = show_progress("Extract", 4, 5)
|
|
126
|
+
|
|
127
|
+
if skip_review:
|
|
128
|
+
# Auto-approve
|
|
129
|
+
context.save_steps(steps_data)
|
|
130
|
+
else:
|
|
131
|
+
# Return for review
|
|
132
|
+
context.save_steps(steps_data) # Save tentative steps
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
'status': 'needs_review',
|
|
136
|
+
'progress': progress,
|
|
137
|
+
'algorithm': {
|
|
138
|
+
'name': algorithm.name,
|
|
139
|
+
'inputs': algorithm.inputs,
|
|
140
|
+
'outputs': algorithm.outputs,
|
|
141
|
+
'steps': steps_data
|
|
142
|
+
},
|
|
143
|
+
'review_interface': review,
|
|
144
|
+
'method': result.method,
|
|
145
|
+
'message': 'Algorithm extracted. Please review before proceeding.',
|
|
146
|
+
'next_steps': [
|
|
147
|
+
'Review and approve extracted steps',
|
|
148
|
+
'Edit steps if needed',
|
|
149
|
+
'Regenerate with clearer text'
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# Progress: Complete
|
|
154
|
+
progress = show_progress("Extract", 5, 5)
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
'status': 'extraction_complete',
|
|
158
|
+
'progress': progress,
|
|
159
|
+
'steps_extracted': len(steps_data),
|
|
160
|
+
'algorithm_name': algorithm.name or (name if name else 'unnamed'),
|
|
161
|
+
'method': result.method,
|
|
162
|
+
'next_steps': [
|
|
163
|
+
'Generate code with /algo-generate',
|
|
164
|
+
'Review extracted steps: /algo-status',
|
|
165
|
+
'Extract a different algorithm: /algo-extract'
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def get_progress_bar(step: int, total: int) -> str:
|
|
171
|
+
"""
|
|
172
|
+
Generate progress bar string: Extract: ████████░░ 80%
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
step: Current step
|
|
176
|
+
total: Total steps
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
Progress bar string
|
|
180
|
+
"""
|
|
181
|
+
return show_progress("Extract", step, total)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Generation workflow for AlgoMath.
|
|
3
|
+
|
|
4
|
+
This module implements the code generation phase, transforming
|
|
5
|
+
extracted algorithm steps into executable Python code.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Dict, List, Optional, Any
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
# Add project root to Python path
|
|
13
|
+
project_root = Path(__file__).parent.parent.parent
|
|
14
|
+
if str(project_root) not in sys.path:
|
|
15
|
+
sys.path.insert(0, str(project_root))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def show_progress(phase: str, current: int, total: int) -> str:
|
|
19
|
+
"""
|
|
20
|
+
Generate a progress bar string.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
phase: Name of the current phase
|
|
24
|
+
current: Current step number
|
|
25
|
+
total: Total number of steps
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
Formatted progress bar string
|
|
29
|
+
"""
|
|
30
|
+
if total <= 0:
|
|
31
|
+
return f"{phase}: ░░░░░░░░░░ 0%"
|
|
32
|
+
|
|
33
|
+
filled = int(10 * current / total)
|
|
34
|
+
filled = max(0, min(filled, 10)) # Clamp to 0-10 range
|
|
35
|
+
bar = '█' * filled + '░' * (10 - filled)
|
|
36
|
+
pct = int(100 * current / total)
|
|
37
|
+
return f"{phase}: {bar} {pct}%"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def run_generation(context: "ContextManager") -> Dict[str, Any]:
|
|
41
|
+
"""
|
|
42
|
+
Generate Python code from extracted steps using TemplateCodeGenerator.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
context: ContextManager instance
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Dict with status and code generation result
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
>>> ctx = ContextManager()
|
|
52
|
+
>>> ctx.start_session()
|
|
53
|
+
>>> ctx.save_steps([{"step": 1, "action": "init"}])
|
|
54
|
+
>>> result = run_generation(ctx)
|
|
55
|
+
>>> print(result['status'])
|
|
56
|
+
'code_generated'
|
|
57
|
+
"""
|
|
58
|
+
# Import here to avoid circular imports
|
|
59
|
+
from algomath.context import ContextManager
|
|
60
|
+
from src.extraction.schema import Algorithm
|
|
61
|
+
from src.generation import HybridCodeGenerator
|
|
62
|
+
|
|
63
|
+
# Progress indicator
|
|
64
|
+
progress = show_progress("Generate", 1, 10)
|
|
65
|
+
|
|
66
|
+
# Load algorithm
|
|
67
|
+
try:
|
|
68
|
+
algorithm_data = context.store.load_session()
|
|
69
|
+
if not algorithm_data.get('algorithm'):
|
|
70
|
+
return {
|
|
71
|
+
'status': 'needs_extraction',
|
|
72
|
+
'progress': progress,
|
|
73
|
+
'message': 'No algorithm found. Extract algorithm first with /algo-extract',
|
|
74
|
+
'next_steps': [
|
|
75
|
+
'Extract algorithm with /algo-extract',
|
|
76
|
+
'Check status with /algo-status'
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
except Exception:
|
|
80
|
+
return {
|
|
81
|
+
'status': 'error',
|
|
82
|
+
'progress': progress,
|
|
83
|
+
'message': 'Could not load algorithm data',
|
|
84
|
+
'next_steps': [
|
|
85
|
+
'Start over with /algo-extract',
|
|
86
|
+
'Show help with /algo-help'
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Convert to Algorithm object
|
|
91
|
+
try:
|
|
92
|
+
algorithm = Algorithm.from_dict(algorithm_data['algorithm'])
|
|
93
|
+
except Exception as e:
|
|
94
|
+
return {
|
|
95
|
+
'status': 'error',
|
|
96
|
+
'progress': progress,
|
|
97
|
+
'message': f'Failed to parse algorithm: {e}',
|
|
98
|
+
'next_steps': ['Extract algorithm again with /algo-extract']
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# Update progress
|
|
102
|
+
progress = show_progress("Generate", 5, 10)
|
|
103
|
+
|
|
104
|
+
# Generate code using hybrid generator (Template → LLM → Stub)
|
|
105
|
+
try:
|
|
106
|
+
generator = HybridCodeGenerator()
|
|
107
|
+
result = generator.generate_for_workflow(algorithm)
|
|
108
|
+
generated = result['generated']
|
|
109
|
+
|
|
110
|
+
# Validate syntax
|
|
111
|
+
if not generated.validation_result.is_valid:
|
|
112
|
+
return {
|
|
113
|
+
'status': 'generation_error',
|
|
114
|
+
'progress': show_progress("Generate", 7, 10),
|
|
115
|
+
'error': generated.validation_result.errors,
|
|
116
|
+
'message': 'Generated code has syntax errors',
|
|
117
|
+
'next_steps': ['Review extraction with /algo-extract', 'Try again with /algo-generate']
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Save to context
|
|
121
|
+
context.save_code(generated.source)
|
|
122
|
+
|
|
123
|
+
# Determine message based on strategy
|
|
124
|
+
strategy = result['strategy']
|
|
125
|
+
messages = {
|
|
126
|
+
'template': 'Generated code using templates',
|
|
127
|
+
'llm': 'Generated code using LLM for complex expressions',
|
|
128
|
+
'stub': 'Generated stub code (full generation failed)'
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# Final progress
|
|
132
|
+
progress = show_progress("Generate", 10, 10)
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
'status': 'code_generated',
|
|
136
|
+
'progress': progress,
|
|
137
|
+
'lines_of_code': len(generated.source.split('\n')),
|
|
138
|
+
'algorithm_name': generated.algorithm_name,
|
|
139
|
+
'strategy': strategy,
|
|
140
|
+
'message': messages.get(strategy, 'Code generated'),
|
|
141
|
+
'next_steps': [
|
|
142
|
+
'Review code with /algo-review',
|
|
143
|
+
'Execute with /algo-run',
|
|
144
|
+
'Regenerate with /algo-generate',
|
|
145
|
+
'Check status with /algo-status'
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
except Exception as e:
|
|
149
|
+
return {
|
|
150
|
+
'status': 'generation_error',
|
|
151
|
+
'progress': show_progress("Generate", 5, 10),
|
|
152
|
+
'error': str(e),
|
|
153
|
+
'message': f'Code generation failed: {e}',
|
|
154
|
+
'next_steps': ['Try again with /algo-generate', 'Review extraction with /algo-extract']
|
|
155
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Execution workflow for AlgoMath.
|
|
3
|
+
|
|
4
|
+
This module implements the code execution phase, running
|
|
5
|
+
generated code in a controlled environment.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Dict, List, Optional, Any
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
# Add project root to Python path
|
|
14
|
+
project_root = Path(__file__).parent.parent.parent
|
|
15
|
+
if str(project_root) not in sys.path:
|
|
16
|
+
sys.path.insert(0, str(project_root))
|
|
17
|
+
|
|
18
|
+
from src.execution import execute_code, ExecutionConfig, ExecutionStatus
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def show_progress(phase: str, current: int, total: int) -> str:
|
|
22
|
+
"""
|
|
23
|
+
Generate a progress bar string.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
phase: Name of the current phase
|
|
27
|
+
current: Current step number
|
|
28
|
+
total: Total number of steps
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Formatted progress bar string
|
|
32
|
+
"""
|
|
33
|
+
if total <= 0:
|
|
34
|
+
return f"{phase}: ░░░░░░░░░░ 0%"
|
|
35
|
+
|
|
36
|
+
filled = int(10 * current / total)
|
|
37
|
+
filled = max(0, min(filled, 10)) # Clamp to 0-10 range
|
|
38
|
+
bar = '█' * filled + '░' * (10 - filled)
|
|
39
|
+
pct = int(100 * current / total)
|
|
40
|
+
return f"{phase}: {bar} {pct}%"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def run_execution(
|
|
44
|
+
context,
|
|
45
|
+
inputs: Optional[Dict[str, Any]] = None,
|
|
46
|
+
skip_execution: bool = False
|
|
47
|
+
) -> Dict[str, Any]:
|
|
48
|
+
"""
|
|
49
|
+
Execute generated code.
|
|
50
|
+
|
|
51
|
+
Per D-21: Auto-triggered after code approval.
|
|
52
|
+
Per D-22: Transitions CODE_GENERATED → EXECUTING → EXECUTION_COMPLETE.
|
|
53
|
+
Per D-23: Shows progress during execution.
|
|
54
|
+
Per D-25: Can skip execution (user controls flow).
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
context: ContextManager instance
|
|
58
|
+
inputs: Optional input data for the algorithm
|
|
59
|
+
skip_execution: If True, skip execution and return mock results
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
Dict with execution status and results
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
>>> ctx = ContextManager()
|
|
66
|
+
>>> ctx.start_session()
|
|
67
|
+
>>> ctx.save_code("def test(): pass")
|
|
68
|
+
>>> result = run_execution(ctx)
|
|
69
|
+
>>> print(result['status'])
|
|
70
|
+
'success'
|
|
71
|
+
"""
|
|
72
|
+
# Progress: Starting per D-23
|
|
73
|
+
progress = show_progress("Execute", 2, 10)
|
|
74
|
+
print(f"\n{progress}")
|
|
75
|
+
print("Setting up execution environment...")
|
|
76
|
+
|
|
77
|
+
# Check if code exists
|
|
78
|
+
try:
|
|
79
|
+
algorithm_data = context.store.load_session()
|
|
80
|
+
code = algorithm_data.get('code', '')
|
|
81
|
+
|
|
82
|
+
if not code:
|
|
83
|
+
return {
|
|
84
|
+
'status': 'needs_generation',
|
|
85
|
+
'progress': progress,
|
|
86
|
+
'message': 'No code found. Generate code first with /algo-generate',
|
|
87
|
+
'next_steps': [
|
|
88
|
+
'Generate code with /algo-generate',
|
|
89
|
+
'Extract algorithm with /algo-extract',
|
|
90
|
+
'Check status with /algo-status'
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
except Exception as e:
|
|
94
|
+
return {
|
|
95
|
+
'status': 'error',
|
|
96
|
+
'progress': progress,
|
|
97
|
+
'message': f'Could not load algorithm data: {e}',
|
|
98
|
+
'next_steps': [
|
|
99
|
+
'Start over with /algo-extract',
|
|
100
|
+
'Show help with /algo-help'
|
|
101
|
+
]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
# Per D-25: Skip execution if requested
|
|
105
|
+
if skip_execution:
|
|
106
|
+
mock_results = {
|
|
107
|
+
'status': 'skipped',
|
|
108
|
+
'stdout': 'Execution skipped per user request.',
|
|
109
|
+
'stderr': '',
|
|
110
|
+
'execution_time': 0.0,
|
|
111
|
+
'return_value': None,
|
|
112
|
+
'error_type': None,
|
|
113
|
+
'error_message': None,
|
|
114
|
+
'timestamp': datetime.now().isoformat()
|
|
115
|
+
}
|
|
116
|
+
context.save_results(mock_results)
|
|
117
|
+
progress = show_progress("Execute", 10, 10)
|
|
118
|
+
return {
|
|
119
|
+
'status': 'skipped',
|
|
120
|
+
'progress': progress,
|
|
121
|
+
'message': 'Execution skipped. Proceed to verification.',
|
|
122
|
+
'next_steps': [
|
|
123
|
+
'Verify manually with /algo-verify',
|
|
124
|
+
'Run with /algo-run',
|
|
125
|
+
'Regenerate with /algo-generate'
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
# Progress: Executing
|
|
130
|
+
progress = show_progress("Execute", 5, 10)
|
|
131
|
+
print(f"\n{progress}")
|
|
132
|
+
print("Running algorithm (timeout: 30s)...")
|
|
133
|
+
|
|
134
|
+
# Configure execution per D-05, D-02
|
|
135
|
+
config = ExecutionConfig(
|
|
136
|
+
timeout=30,
|
|
137
|
+
max_memory_mb=512
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
# Execute code
|
|
141
|
+
result = execute_code(code, inputs=inputs, config=config)
|
|
142
|
+
|
|
143
|
+
# Progress: Saving
|
|
144
|
+
progress = show_progress("Execute", 8, 10)
|
|
145
|
+
print(f"\n{progress}")
|
|
146
|
+
print("Capturing results...")
|
|
147
|
+
|
|
148
|
+
# Format results for context per D-16
|
|
149
|
+
results_data = {
|
|
150
|
+
'status': result.status.value,
|
|
151
|
+
'stdout': result.stdout,
|
|
152
|
+
'stderr': result.stderr,
|
|
153
|
+
'execution_time': result.runtime_seconds,
|
|
154
|
+
'return_value': result.return_value,
|
|
155
|
+
'error_type': result.error_type,
|
|
156
|
+
'error_message': result.error_message,
|
|
157
|
+
'timestamp': datetime.now().isoformat()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
# Save to context (triggers EXECUTION_COMPLETE transition per D-22)
|
|
161
|
+
context.save_results(results_data)
|
|
162
|
+
|
|
163
|
+
# Final progress per D-23
|
|
164
|
+
progress = show_progress("Execute", 10, 10)
|
|
165
|
+
|
|
166
|
+
# Build response per D-18
|
|
167
|
+
if result.status == ExecutionStatus.SUCCESS:
|
|
168
|
+
message = f"✓ Execution complete in {result.runtime_seconds:.3f}s"
|
|
169
|
+
elif result.status == ExecutionStatus.TIMEOUT:
|
|
170
|
+
message = "⚠ Execution timed out (30s limit). Check for infinite loops."
|
|
171
|
+
else:
|
|
172
|
+
message = f"✗ Execution failed: {result.error_message or result.error_type or 'Unknown error'}"
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
'status': result.status.value,
|
|
176
|
+
'progress': progress,
|
|
177
|
+
'execution_time': result.runtime_seconds,
|
|
178
|
+
'stdout': result.stdout[:2000] if result.stdout else '', # per D-15
|
|
179
|
+
'stderr': result.stderr[:1000] if result.stderr else '',
|
|
180
|
+
'error': result.error_message if result.status != ExecutionStatus.SUCCESS else None,
|
|
181
|
+
'message': message,
|
|
182
|
+
'next_steps': [
|
|
183
|
+
'Verify results with /algo-verify',
|
|
184
|
+
'Run again with /algo-run',
|
|
185
|
+
'Regenerate code with /algo-generate'
|
|
186
|
+
]
|
|
187
|
+
}
|