pdd-cli 0.0.24__py3-none-any.whl → 0.0.26__py3-none-any.whl
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.
Potentially problematic release.
This version of pdd-cli might be problematic. Click here for more details.
- pdd/__init__.py +14 -1
- pdd/bug_main.py +5 -1
- pdd/bug_to_unit_test.py +16 -5
- pdd/change.py +2 -1
- pdd/change_main.py +407 -189
- pdd/cli.py +853 -301
- pdd/code_generator.py +2 -1
- pdd/conflicts_in_prompts.py +2 -1
- pdd/construct_paths.py +377 -222
- pdd/context_generator.py +2 -1
- pdd/continue_generation.py +5 -2
- pdd/crash_main.py +55 -20
- pdd/data/llm_model.csv +18 -17
- pdd/detect_change.py +2 -1
- pdd/fix_code_loop.py +465 -160
- pdd/fix_code_module_errors.py +7 -4
- pdd/fix_error_loop.py +9 -9
- pdd/fix_errors_from_unit_tests.py +207 -365
- pdd/fix_main.py +32 -4
- pdd/fix_verification_errors.py +148 -77
- pdd/fix_verification_errors_loop.py +842 -768
- pdd/fix_verification_main.py +412 -0
- pdd/generate_output_paths.py +427 -189
- pdd/generate_test.py +3 -2
- pdd/increase_tests.py +2 -2
- pdd/llm_invoke.py +1167 -343
- pdd/preprocess.py +3 -3
- pdd/process_csv_change.py +466 -154
- pdd/prompts/bug_to_unit_test_LLM.prompt +11 -11
- pdd/prompts/extract_prompt_update_LLM.prompt +11 -5
- pdd/prompts/extract_unit_code_fix_LLM.prompt +2 -2
- pdd/prompts/find_verification_errors_LLM.prompt +11 -9
- pdd/prompts/fix_code_module_errors_LLM.prompt +29 -0
- pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +5 -5
- pdd/prompts/fix_verification_errors_LLM.prompt +8 -1
- pdd/prompts/generate_test_LLM.prompt +9 -3
- pdd/prompts/trim_results_start_LLM.prompt +1 -1
- pdd/prompts/update_prompt_LLM.prompt +3 -3
- pdd/split.py +6 -5
- pdd/split_main.py +13 -4
- pdd/trace_main.py +7 -0
- pdd/update_model_costs.py +446 -0
- pdd/xml_tagger.py +2 -1
- {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.26.dist-info}/METADATA +8 -16
- {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.26.dist-info}/RECORD +49 -47
- {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.26.dist-info}/WHEEL +1 -1
- {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.26.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.26.dist-info}/licenses/LICENSE +0 -0
- {pdd_cli-0.0.24.dist-info → pdd_cli-0.0.26.dist-info}/top_level.txt +0 -0
pdd/fix_main.py
CHANGED
|
@@ -2,10 +2,12 @@ import sys
|
|
|
2
2
|
from typing import Tuple, Optional
|
|
3
3
|
import click
|
|
4
4
|
from rich import print as rprint
|
|
5
|
+
from rich.markup import MarkupError, escape
|
|
5
6
|
|
|
6
7
|
import requests
|
|
7
8
|
import asyncio
|
|
8
9
|
import os
|
|
10
|
+
from pathlib import Path
|
|
9
11
|
|
|
10
12
|
from .preprocess import preprocess
|
|
11
13
|
|
|
@@ -15,6 +17,9 @@ from .fix_error_loop import fix_error_loop
|
|
|
15
17
|
from .get_jwt_token import get_jwt_token
|
|
16
18
|
from .get_language import get_language
|
|
17
19
|
|
|
20
|
+
# Import DEFAULT_STRENGTH from the package
|
|
21
|
+
from . import DEFAULT_STRENGTH
|
|
22
|
+
|
|
18
23
|
def fix_main(
|
|
19
24
|
ctx: click.Context,
|
|
20
25
|
prompt_file: str,
|
|
@@ -65,6 +70,12 @@ def fix_main(
|
|
|
65
70
|
analysis_results = None
|
|
66
71
|
|
|
67
72
|
try:
|
|
73
|
+
# Verify error file exists if not in loop mode
|
|
74
|
+
if not loop:
|
|
75
|
+
error_path = Path(error_file)
|
|
76
|
+
if not error_path.exists():
|
|
77
|
+
raise FileNotFoundError(f"Error file '{error_file}' does not exist.")
|
|
78
|
+
|
|
68
79
|
# Construct file paths
|
|
69
80
|
input_file_paths = {
|
|
70
81
|
"prompt_file": prompt_file,
|
|
@@ -85,11 +96,12 @@ def fix_main(
|
|
|
85
96
|
force=ctx.obj.get('force', False),
|
|
86
97
|
quiet=ctx.obj.get('quiet', False),
|
|
87
98
|
command="fix",
|
|
88
|
-
command_options=command_options
|
|
99
|
+
command_options=command_options,
|
|
100
|
+
create_error_file=loop # Only create error file if in loop mode
|
|
89
101
|
)
|
|
90
102
|
|
|
91
103
|
# Get parameters from context
|
|
92
|
-
strength = ctx.obj.get('strength',
|
|
104
|
+
strength = ctx.obj.get('strength', DEFAULT_STRENGTH)
|
|
93
105
|
temperature = ctx.obj.get('temperature', 0)
|
|
94
106
|
verbose = ctx.obj.get('verbose', False)
|
|
95
107
|
if loop:
|
|
@@ -139,7 +151,16 @@ def fix_main(
|
|
|
139
151
|
if verbose and analysis_results:
|
|
140
152
|
# Log the first 200 characters of analysis if in verbose mode
|
|
141
153
|
analysis_preview = analysis_results[:200] + "..." if len(analysis_results) > 200 else analysis_results
|
|
142
|
-
|
|
154
|
+
try:
|
|
155
|
+
# Attempt to print the preview using rich markup parsing
|
|
156
|
+
rprint(f"[bold]Analysis preview:[/bold] {analysis_preview}")
|
|
157
|
+
except MarkupError as me:
|
|
158
|
+
# If markup fails, print a warning and the escaped preview
|
|
159
|
+
rprint(f"[bold yellow]Warning:[/bold yellow] Analysis preview contained invalid markup: {me}")
|
|
160
|
+
rprint(f"[bold]Raw Analysis preview (escaped):[/bold] {escape(analysis_preview)}")
|
|
161
|
+
except Exception as e:
|
|
162
|
+
# Handle other potential errors during preview printing
|
|
163
|
+
rprint(f"[bold red]Error printing analysis preview: {e}[/bold red]")
|
|
143
164
|
if success:
|
|
144
165
|
rprint("[bold green]Fixed files saved:[/bold green]")
|
|
145
166
|
rprint(f" Test file: {output_file_paths['output_test']}")
|
|
@@ -263,5 +284,12 @@ def fix_main(
|
|
|
263
284
|
|
|
264
285
|
except Exception as e:
|
|
265
286
|
if not ctx.obj.get('quiet', False):
|
|
266
|
-
|
|
287
|
+
# Safely handle and print MarkupError
|
|
288
|
+
if isinstance(e, MarkupError):
|
|
289
|
+
rprint(f"[bold red]Markup Error in fix_main:[/bold red]")
|
|
290
|
+
rprint(escape(str(e)))
|
|
291
|
+
else:
|
|
292
|
+
# Print other errors normally, escaping the error string
|
|
293
|
+
from rich.markup import escape # Ensure escape is imported
|
|
294
|
+
rprint(f"[bold red]Error:[/bold red] {escape(str(e))}")
|
|
267
295
|
sys.exit(1)
|
pdd/fix_verification_errors.py
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
import re
|
|
2
|
-
from typing import Dict, Any
|
|
2
|
+
from typing import Dict, Any, Optional
|
|
3
3
|
from rich import print as rprint
|
|
4
4
|
from rich.markdown import Markdown
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
5
6
|
from .load_prompt_template import load_prompt_template
|
|
6
7
|
from .llm_invoke import llm_invoke
|
|
7
8
|
|
|
9
|
+
# Define Pydantic model for structured LLM output for VERIFICATION
|
|
10
|
+
class VerificationOutput(BaseModel):
|
|
11
|
+
issues_count: int = Field(description="The number of issues found during verification.")
|
|
12
|
+
details: Optional[str] = Field(description="Detailed explanation of any discrepancies or issues found. Can be null or empty if issues_count is 0.", default=None)
|
|
13
|
+
|
|
14
|
+
# Define Pydantic model for structured LLM output for FIXES
|
|
15
|
+
class FixerOutput(BaseModel):
|
|
16
|
+
explanation: str = Field(description="Detailed explanation of the analysis and fixes applied.")
|
|
17
|
+
fixed_code: str = Field(description="The complete, runnable, and fixed code module.")
|
|
18
|
+
fixed_program: str = Field(description="The complete, runnable, and fixed program that uses the code module.")
|
|
19
|
+
|
|
8
20
|
def fix_verification_errors(
|
|
9
21
|
program: str,
|
|
10
22
|
prompt: str,
|
|
@@ -41,12 +53,13 @@ def fix_verification_errors(
|
|
|
41
53
|
verification_issues_count = 0
|
|
42
54
|
verification_details = None
|
|
43
55
|
fix_explanation = None
|
|
44
|
-
fixed_program = program
|
|
45
|
-
fixed_code = code
|
|
56
|
+
fixed_program = program # Initialize with original program
|
|
57
|
+
fixed_code = code # Initialize with original code
|
|
46
58
|
final_explanation = None
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
60
|
+
# Check only essential inputs, allow empty output
|
|
61
|
+
if not all([program, prompt, code]):
|
|
62
|
+
rprint("[bold red]Error:[/bold red] Missing one or more required inputs (program, prompt, code).")
|
|
50
63
|
return {
|
|
51
64
|
"explanation": None,
|
|
52
65
|
"fixed_program": program,
|
|
@@ -103,10 +116,10 @@ def fix_verification_errors(
|
|
|
103
116
|
strength=strength,
|
|
104
117
|
temperature=temperature,
|
|
105
118
|
verbose=False,
|
|
119
|
+
output_pydantic=VerificationOutput
|
|
106
120
|
)
|
|
107
121
|
total_cost += verification_response.get('cost', 0.0)
|
|
108
122
|
model_name = verification_response.get('model_name', model_name)
|
|
109
|
-
verification_result = verification_response.get('result', '')
|
|
110
123
|
|
|
111
124
|
if verbose:
|
|
112
125
|
rprint(f"[cyan]Verification LLM call complete.[/cyan]")
|
|
@@ -121,52 +134,90 @@ def fix_verification_errors(
|
|
|
121
134
|
"fixed_code": code,
|
|
122
135
|
"total_cost": total_cost,
|
|
123
136
|
"model_name": model_name,
|
|
124
|
-
"verification_issues_count":
|
|
137
|
+
"verification_issues_count": 0, # Reset on LLM call error
|
|
125
138
|
}
|
|
126
139
|
|
|
127
|
-
if verbose:
|
|
128
|
-
rprint("\n[blue]Verification Result:[/blue]")
|
|
129
|
-
rprint(Markdown(verification_result))
|
|
130
|
-
|
|
131
140
|
issues_found = False
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
verification_result_obj = verification_response.get('result')
|
|
142
|
+
|
|
143
|
+
if isinstance(verification_result_obj, VerificationOutput):
|
|
144
|
+
verification_issues_count = verification_result_obj.issues_count
|
|
145
|
+
verification_details = verification_result_obj.details
|
|
146
|
+
if verbose:
|
|
147
|
+
rprint("[green]Successfully parsed structured output from verification LLM.[/green]")
|
|
148
|
+
rprint("\n[blue]Verification Result (parsed):[/blue]")
|
|
149
|
+
rprint(f" Issues Count: {verification_issues_count}")
|
|
150
|
+
if verification_details:
|
|
151
|
+
rprint(Markdown(f"**Details:**\n{verification_details}"))
|
|
152
|
+
else:
|
|
153
|
+
rprint(" Details: None provided or no issues found.")
|
|
139
154
|
|
|
140
155
|
if verification_issues_count > 0:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
issues_found = True
|
|
146
|
-
if verbose:
|
|
147
|
-
rprint(f"\n[yellow]Found {verification_issues_count} potential issues. Proceeding to fix step.[/yellow]")
|
|
148
|
-
else:
|
|
149
|
-
rprint("[yellow]Warning:[/yellow] <issues_count> is > 0, but <details> tag is empty. Treating as no issues found.")
|
|
150
|
-
verification_issues_count = 0
|
|
156
|
+
if verification_details and verification_details.strip():
|
|
157
|
+
issues_found = True
|
|
158
|
+
if verbose:
|
|
159
|
+
rprint(f"\n[yellow]Found {verification_issues_count} potential issues. Proceeding to fix step.[/yellow]")
|
|
151
160
|
else:
|
|
152
|
-
rprint("[yellow]Warning:[/yellow] <issues_count> is
|
|
161
|
+
rprint(f"[yellow]Warning:[/yellow] <issues_count> is {verification_issues_count}, but <details> field is empty or missing. Treating as no actionable issues found.")
|
|
153
162
|
verification_issues_count = 0
|
|
154
163
|
else:
|
|
155
164
|
if verbose:
|
|
156
|
-
rprint("\n[green]No issues found during verification.[/green]")
|
|
165
|
+
rprint("\n[green]No issues found during verification based on structured output.[/green]")
|
|
166
|
+
elif isinstance(verification_result_obj, str):
|
|
167
|
+
try:
|
|
168
|
+
issues_match = re.search(r'<issues_count>(\d+)</issues_count>', verification_result_obj)
|
|
169
|
+
if issues_match:
|
|
170
|
+
parsed_issues_count = int(issues_match.group(1))
|
|
171
|
+
details_match = re.search(r'<details>(.*?)</details>', verification_result_obj, re.DOTALL)
|
|
172
|
+
parsed_verification_details = details_match.group(1).strip() if (details_match and details_match.group(1)) else None
|
|
157
173
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
174
|
+
|
|
175
|
+
if parsed_issues_count > 0:
|
|
176
|
+
if parsed_verification_details: # Check if details exist and are not empty
|
|
177
|
+
issues_found = True
|
|
178
|
+
verification_issues_count = parsed_issues_count
|
|
179
|
+
verification_details = parsed_verification_details
|
|
180
|
+
if verbose:
|
|
181
|
+
rprint(f"\n[yellow]Found {verification_issues_count} potential issues in string response. Proceeding to fix step.[/yellow]")
|
|
182
|
+
else:
|
|
183
|
+
rprint(f"[yellow]Warning:[/yellow] <issues_count> is {parsed_issues_count} in string response, but <details> field is empty or missing. Treating as no actionable issues found.")
|
|
184
|
+
verification_issues_count = 0
|
|
185
|
+
issues_found = False
|
|
186
|
+
else: # parsed_issues_count == 0
|
|
187
|
+
verification_issues_count = 0
|
|
188
|
+
issues_found = False
|
|
189
|
+
if verbose:
|
|
190
|
+
rprint("\n[green]No issues found in string verification based on <issues_count> being 0.[/green]")
|
|
191
|
+
else: # issues_match is None (tag not found or content not digits)
|
|
192
|
+
rprint("[bold red]Error:[/bold red] Could not find or parse integer value from <issues_count> tag in string response.")
|
|
193
|
+
return {
|
|
194
|
+
"explanation": None,
|
|
195
|
+
"fixed_program": program,
|
|
196
|
+
"fixed_code": code,
|
|
197
|
+
"total_cost": total_cost,
|
|
198
|
+
"model_name": model_name,
|
|
199
|
+
"verification_issues_count": 0,
|
|
200
|
+
}
|
|
201
|
+
except ValueError: # Should not be hit if regex is \d+, but as a safeguard
|
|
202
|
+
rprint("[bold red]Error:[/bold red] Invalid non-integer value in <issues_count> tag in string response.")
|
|
203
|
+
return {
|
|
204
|
+
"explanation": None,
|
|
205
|
+
"fixed_program": program,
|
|
206
|
+
"fixed_code": code,
|
|
207
|
+
"total_cost": total_cost,
|
|
208
|
+
"model_name": model_name,
|
|
209
|
+
"verification_issues_count": 0,
|
|
210
|
+
}
|
|
211
|
+
else: # Not VerificationOutput and not a successfully parsed string
|
|
212
|
+
rprint(f"[bold red]Error:[/bold red] Verification LLM call did not return the expected structured output (e.g., parsing failed).")
|
|
213
|
+
rprint(f" [dim]Expected type:[/dim] {VerificationOutput} or str")
|
|
214
|
+
rprint(f" [dim]Received type:[/dim] {type(verification_result_obj)}")
|
|
215
|
+
content_str = str(verification_result_obj)
|
|
216
|
+
rprint(f" [dim]Received content:[/dim] {content_str[:500]}{'...' if len(content_str) > 500 else ''}")
|
|
217
|
+
raw_text = verification_response.get('result_text')
|
|
218
|
+
if raw_text:
|
|
219
|
+
raw_text_str = str(raw_text)
|
|
220
|
+
rprint(f" [dim]Raw LLM text (if available from llm_invoke):[/dim] {raw_text_str[:500]}{'...' if len(raw_text_str) > 500 else ''}")
|
|
170
221
|
return {
|
|
171
222
|
"explanation": None,
|
|
172
223
|
"fixed_program": program,
|
|
@@ -195,59 +246,79 @@ def fix_verification_errors(
|
|
|
195
246
|
strength=strength,
|
|
196
247
|
temperature=temperature,
|
|
197
248
|
verbose=False,
|
|
249
|
+
output_pydantic=FixerOutput
|
|
198
250
|
)
|
|
199
251
|
total_cost += fix_response.get('cost', 0.0)
|
|
200
252
|
model_name = fix_response.get('model_name', model_name)
|
|
201
|
-
fix_result = fix_response.get('result', '')
|
|
202
253
|
|
|
203
254
|
if verbose:
|
|
204
255
|
rprint(f"[cyan]Fix LLM call complete.[/cyan]")
|
|
205
256
|
rprint(f" [dim]Model Used:[/dim] {fix_response.get('model_name', 'N/A')}")
|
|
206
257
|
rprint(f" [dim]Cost:[/dim] ${fix_response.get('cost', 0.0):.6f}")
|
|
207
|
-
rprint("\n[blue]Fix Result:[/blue]")
|
|
208
|
-
rprint(Markdown(fix_result))
|
|
209
258
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
explanation_match = re.search(r"<explanation>(.*?)</explanation>", fix_result, re.DOTALL)
|
|
259
|
+
fix_result_obj = fix_response.get('result')
|
|
260
|
+
parsed_fix_successfully = False
|
|
213
261
|
|
|
214
|
-
if
|
|
215
|
-
fixed_program =
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
262
|
+
if isinstance(fix_result_obj, FixerOutput):
|
|
263
|
+
fixed_program = fix_result_obj.fixed_program
|
|
264
|
+
fixed_code = fix_result_obj.fixed_code
|
|
265
|
+
fix_explanation = fix_result_obj.explanation
|
|
266
|
+
parsed_fix_successfully = True
|
|
267
|
+
if verbose:
|
|
268
|
+
rprint("[green]Successfully parsed structured output for fix.[/green]")
|
|
269
|
+
rprint(Markdown(f"**Explanation from LLM:**\n{fix_explanation}"))
|
|
270
|
+
elif isinstance(fix_result_obj, str):
|
|
271
|
+
program_match = re.search(r'<fixed_program>(.*?)</fixed_program>', fix_result_obj, re.DOTALL)
|
|
272
|
+
code_match = re.search(r'<fixed_code>(.*?)</fixed_code>', fix_result_obj, re.DOTALL)
|
|
273
|
+
explanation_match = re.search(r'<explanation>(.*?)</explanation>', fix_result_obj, re.DOTALL)
|
|
219
274
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if verbose: rprint("[yellow]Warning:[/yellow] Could not find <fixed_code> tag in fix result. Using original code module.")
|
|
275
|
+
if program_match or code_match or explanation_match: # If any tag is found, attempt to parse
|
|
276
|
+
fixed_program_candidate = program_match.group(1).strip() if (program_match and program_match.group(1)) else None
|
|
277
|
+
fixed_code_candidate = code_match.group(1).strip() if (code_match and code_match.group(1)) else None
|
|
278
|
+
fix_explanation_candidate = explanation_match.group(1).strip() if (explanation_match and explanation_match.group(1)) else None
|
|
225
279
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if verbose: rprint("[yellow]Warning:[/yellow] Could not find <explanation> tag in fix result.")
|
|
231
|
-
fix_explanation = "[Fix explanation not provided by LLM]"
|
|
280
|
+
fixed_program = fixed_program_candidate if fixed_program_candidate else program
|
|
281
|
+
fixed_code = fixed_code_candidate if fixed_code_candidate else code
|
|
282
|
+
fix_explanation = fix_explanation_candidate if fix_explanation_candidate else "[Fix explanation not provided by LLM]"
|
|
283
|
+
parsed_fix_successfully = True
|
|
232
284
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
285
|
+
if verbose:
|
|
286
|
+
if not program_match or not fixed_program_candidate:
|
|
287
|
+
rprint("[yellow]Warning:[/yellow] Could not find or parse <fixed_program> tag in fix result string. Using original program.")
|
|
288
|
+
if not code_match or not fixed_code_candidate:
|
|
289
|
+
rprint("[yellow]Warning:[/yellow] Could not find or parse <fixed_code> tag in fix result string. Using original code module.")
|
|
290
|
+
if not explanation_match or not fix_explanation_candidate:
|
|
291
|
+
rprint("[yellow]Warning:[/yellow] Could not find or parse <explanation> tag in fix result string. Using default explanation.")
|
|
292
|
+
# else: string, but no relevant tags. Will fall to parsed_fix_successfully = False below
|
|
237
293
|
|
|
238
|
-
|
|
239
|
-
|
|
294
|
+
if not parsed_fix_successfully:
|
|
295
|
+
rprint(f"[bold red]Error:[/bold red] Fix generation LLM call did not return the expected structured output (e.g., parsing failed).")
|
|
296
|
+
rprint(f" [dim]Expected type:[/dim] {FixerOutput} or str (with XML tags)")
|
|
297
|
+
rprint(f" [dim]Received type:[/dim] {type(fix_result_obj)}")
|
|
298
|
+
content_str = str(fix_result_obj)
|
|
299
|
+
rprint(f" [dim]Received content:[/dim] {content_str[:500]}{'...' if len(content_str) > 500 else ''}")
|
|
300
|
+
raw_text = fix_response.get('result_text')
|
|
301
|
+
if raw_text:
|
|
302
|
+
raw_text_str = str(raw_text)
|
|
303
|
+
rprint(f" [dim]Raw LLM text (if available from llm_invoke):[/dim] {raw_text_str[:500]}{'...' if len(raw_text_str) > 500 else ''}")
|
|
304
|
+
fix_explanation = "[Error: Failed to parse structured output from LLM for fix explanation]"
|
|
305
|
+
# fixed_program and fixed_code remain original (already initialized)
|
|
306
|
+
|
|
307
|
+
except Exception as e:
|
|
308
|
+
rprint(f"[bold red]Error during fix LLM call or processing structured output:[/bold red] {e}")
|
|
309
|
+
fix_explanation = f"[Error during fix generation: {e}]"
|
|
310
|
+
# fixed_program and fixed_code remain original
|
|
240
311
|
|
|
241
|
-
if issues_found
|
|
312
|
+
if issues_found:
|
|
242
313
|
final_explanation = (
|
|
243
314
|
f"<verification_details>{verification_details}</verification_details>\n"
|
|
244
315
|
f"<fix_explanation>{fix_explanation}</fix_explanation>"
|
|
245
316
|
)
|
|
246
|
-
|
|
247
|
-
final_explanation =
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
)
|
|
317
|
+
else:
|
|
318
|
+
final_explanation = None # Or "" if an empty list/None is preferred per prompt for "no issues"
|
|
319
|
+
|
|
320
|
+
if verbose:
|
|
321
|
+
rprint(f"\n[bold blue]Total Cost for fix_verification_errors run:[/bold blue] ${total_cost:.6f}")
|
|
251
322
|
|
|
252
323
|
return {
|
|
253
324
|
"explanation": final_explanation,
|
|
@@ -256,4 +327,4 @@ def fix_verification_errors(
|
|
|
256
327
|
"total_cost": total_cost,
|
|
257
328
|
"model_name": model_name,
|
|
258
329
|
"verification_issues_count": verification_issues_count,
|
|
259
|
-
}
|
|
330
|
+
}
|