Skip to content

Commit df29969

Browse files
Merge branch 'main' into ashraf/cf-918-fix-vsc-extension-windows-bugs
2 parents 1d0802d + 92870b2 commit df29969

28 files changed

Lines changed: 2234 additions & 408 deletions

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,9 @@ fabric.properties
254254

255255
# Mac
256256
.DS_Store
257-
WARP.MD
257+
WARP.MD
258+
259+
.mcp.json
260+
.tessl/
261+
CLAUDE.md
262+
tessl.json

AGENTS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,4 +315,8 @@ Language Server Protocol support in `codeflash/lsp/` enables IDE integration dur
315315
### Performance Optimization
316316
- Profile before and after changes
317317
- Use benchmarks to validate improvements
318-
- Generate detailed performance reports
318+
- Generate detailed performance reports
319+
320+
# Agent Rules <!-- tessl-managed -->
321+
322+
@.tessl/RULES.md follow the [instructions](.tessl/RULES.md)

codeflash/api/aiservice.py

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@
1818
from codeflash.code_utils.time_utils import humanize_runtime
1919
from codeflash.lsp.helpers import is_LSP_enabled
2020
from codeflash.models.ExperimentMetadata import ExperimentMetadata
21-
from codeflash.models.models import AIServiceRefinerRequest, CodeStringsMarkdown, OptimizedCandidate
21+
from codeflash.models.models import (
22+
AIServiceRefinerRequest,
23+
CodeStringsMarkdown,
24+
OptimizedCandidate,
25+
OptimizedCandidateSource,
26+
)
2227
from codeflash.telemetry.posthog_cf import ph
2328
from codeflash.version import __version__ as codeflash_version
2429

@@ -27,7 +32,7 @@
2732

2833
from codeflash.discovery.functions_to_optimize import FunctionToOptimize
2934
from codeflash.models.ExperimentMetadata import ExperimentMetadata
30-
from codeflash.models.models import AIServiceRefinerRequest
35+
from codeflash.models.models import AIServiceCodeRepairRequest, AIServiceRefinerRequest
3136
from codeflash.result.explanation import Explanation
3237

3338

@@ -86,15 +91,21 @@ def make_ai_service_request(
8691
# response.raise_for_status() # Will raise an HTTPError if the HTTP request returned an unsuccessful status code
8792
return response
8893

89-
def _get_valid_candidates(self, optimizations_json: list[dict[str, Any]]) -> list[OptimizedCandidate]:
94+
def _get_valid_candidates(
95+
self, optimizations_json: list[dict[str, Any]], source: OptimizedCandidateSource
96+
) -> list[OptimizedCandidate]:
9097
candidates: list[OptimizedCandidate] = []
9198
for opt in optimizations_json:
9299
code = CodeStringsMarkdown.parse_markdown_code(opt["source_code"])
93100
if not code.code_strings:
94101
continue
95102
candidates.append(
96103
OptimizedCandidate(
97-
source_code=code, explanation=opt["explanation"], optimization_id=opt["optimization_id"]
104+
source_code=code,
105+
explanation=opt["explanation"],
106+
optimization_id=opt["optimization_id"],
107+
source=source,
108+
parent_id=opt.get("parent_id", None),
98109
)
99110
)
100111
return candidates
@@ -156,7 +167,7 @@ def optimize_python_code( # noqa: D417
156167
console.rule()
157168
end_time = time.perf_counter()
158169
logger.debug(f"!lsp|Generating possible optimizations took {end_time - start_time:.2f} seconds.")
159-
return self._get_valid_candidates(optimizations_json)
170+
return self._get_valid_candidates(optimizations_json, OptimizedCandidateSource.OPTIMIZE)
160171
try:
161172
error = response.json()["error"]
162173
except Exception:
@@ -221,7 +232,7 @@ def optimize_python_code_line_profiler( # noqa: D417
221232
f"!lsp|Generated {len(optimizations_json)} candidate optimizations using line profiler information."
222233
)
223234
console.rule()
224-
return self._get_valid_candidates(optimizations_json)
235+
return self._get_valid_candidates(optimizations_json, OptimizedCandidateSource.OPTIMIZE_LP)
225236
try:
226237
error = response.json()["error"]
227238
except Exception:
@@ -248,20 +259,18 @@ def optimize_python_code_refinement(self, request: list[AIServiceRefinerRequest]
248259
"original_source_code": opt.original_source_code,
249260
"read_only_dependency_code": opt.read_only_dependency_code,
250261
"original_line_profiler_results": opt.original_line_profiler_results,
251-
"original_code_runtime": opt.original_code_runtime,
262+
"original_code_runtime": humanize_runtime(opt.original_code_runtime),
252263
"optimized_source_code": opt.optimized_source_code,
253264
"optimized_explanation": opt.optimized_explanation,
254265
"optimized_line_profiler_results": opt.optimized_line_profiler_results,
255-
"optimized_code_runtime": opt.optimized_code_runtime,
266+
"optimized_code_runtime": humanize_runtime(opt.optimized_code_runtime),
256267
"speedup": opt.speedup,
257268
"trace_id": opt.trace_id,
258269
"function_references": opt.function_references,
259270
"python_version": platform.python_version(),
260271
}
261272
for opt in request
262273
]
263-
logger.debug(f"Refining {len(request)} optimizations…")
264-
console.rule()
265274
try:
266275
response = self.make_ai_service_request("/refinement", payload=payload, timeout=120)
267276
except requests.exceptions.RequestException as e:
@@ -271,18 +280,8 @@ def optimize_python_code_refinement(self, request: list[AIServiceRefinerRequest]
271280

272281
if response.status_code == 200:
273282
refined_optimizations = response.json()["refinements"]
274-
logger.debug(f"Generated {len(refined_optimizations)} candidate refinements.")
275-
console.rule()
276283

277-
refinements = self._get_valid_candidates(refined_optimizations)
278-
return [
279-
OptimizedCandidate(
280-
source_code=c.source_code,
281-
explanation=c.explanation,
282-
optimization_id=c.optimization_id[:-4] + "refi",
283-
)
284-
for c in refinements
285-
]
284+
return self._get_valid_candidates(refined_optimizations, OptimizedCandidateSource.REFINE)
286285

287286
try:
288287
error = response.json()["error"]
@@ -293,6 +292,52 @@ def optimize_python_code_refinement(self, request: list[AIServiceRefinerRequest]
293292
console.rule()
294293
return []
295294

295+
def code_repair(self, request: AIServiceCodeRepairRequest) -> OptimizedCandidate | None:
296+
"""Repair the optimization candidate that is not matching the test result of the original code.
297+
298+
Args:
299+
request: candidate details for repair
300+
301+
Returns:
302+
-------
303+
- OptimizedCandidate: new fixed candidate.
304+
305+
"""
306+
console.rule()
307+
try:
308+
payload = {
309+
"optimization_id": request.optimization_id,
310+
"original_source_code": request.original_source_code,
311+
"modified_source_code": request.modified_source_code,
312+
"trace_id": request.trace_id,
313+
"test_diffs": request.test_diffs,
314+
}
315+
response = self.make_ai_service_request("/code_repair", payload=payload, timeout=120)
316+
except (requests.exceptions.RequestException, TypeError) as e:
317+
logger.exception(f"Error generating optimization repair: {e}")
318+
ph("cli-optimize-error-caught", {"error": str(e)})
319+
return None
320+
321+
if response.status_code == 200:
322+
fixed_optimization = response.json()
323+
console.rule()
324+
325+
valid_candidates = self._get_valid_candidates([fixed_optimization], OptimizedCandidateSource.REPAIR)
326+
if not valid_candidates:
327+
logger.error("Code repair failed to generate a valid candidate.")
328+
return None
329+
330+
return valid_candidates[0]
331+
332+
try:
333+
error = response.json()["error"]
334+
except Exception:
335+
error = response.text
336+
logger.error(f"Error generating optimized candidates: {response.status_code} - {error}")
337+
ph("cli-optimize-error-response", {"response_status_code": response.status_code, "error": error})
338+
console.rule()
339+
return None
340+
296341
def get_new_explanation( # noqa: D417
297342
self,
298343
source_code: str,

0 commit comments

Comments
 (0)