pdd-cli 0.0.45__py3-none-any.whl → 0.0.90__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.
- pdd/__init__.py +4 -4
- pdd/agentic_common.py +863 -0
- pdd/agentic_crash.py +534 -0
- pdd/agentic_fix.py +1179 -0
- pdd/agentic_langtest.py +162 -0
- pdd/agentic_update.py +370 -0
- pdd/agentic_verify.py +183 -0
- pdd/auto_deps_main.py +15 -5
- pdd/auto_include.py +63 -5
- pdd/bug_main.py +3 -2
- pdd/bug_to_unit_test.py +2 -0
- pdd/change_main.py +11 -4
- pdd/cli.py +22 -1181
- pdd/cmd_test_main.py +73 -21
- pdd/code_generator.py +58 -18
- pdd/code_generator_main.py +672 -25
- pdd/commands/__init__.py +42 -0
- pdd/commands/analysis.py +248 -0
- pdd/commands/fix.py +140 -0
- pdd/commands/generate.py +257 -0
- pdd/commands/maintenance.py +174 -0
- pdd/commands/misc.py +79 -0
- pdd/commands/modify.py +230 -0
- pdd/commands/report.py +144 -0
- pdd/commands/templates.py +215 -0
- pdd/commands/utility.py +110 -0
- pdd/config_resolution.py +58 -0
- pdd/conflicts_main.py +8 -3
- pdd/construct_paths.py +258 -82
- pdd/context_generator.py +10 -2
- pdd/context_generator_main.py +113 -11
- pdd/continue_generation.py +47 -7
- pdd/core/__init__.py +0 -0
- pdd/core/cli.py +503 -0
- pdd/core/dump.py +554 -0
- pdd/core/errors.py +63 -0
- pdd/core/utils.py +90 -0
- pdd/crash_main.py +44 -11
- pdd/data/language_format.csv +71 -63
- pdd/data/llm_model.csv +20 -18
- pdd/detect_change_main.py +5 -4
- pdd/fix_code_loop.py +330 -76
- pdd/fix_error_loop.py +207 -61
- pdd/fix_errors_from_unit_tests.py +4 -3
- pdd/fix_main.py +75 -18
- pdd/fix_verification_errors.py +12 -100
- pdd/fix_verification_errors_loop.py +306 -272
- pdd/fix_verification_main.py +28 -9
- pdd/generate_output_paths.py +93 -10
- pdd/generate_test.py +16 -5
- pdd/get_jwt_token.py +9 -2
- pdd/get_run_command.py +73 -0
- pdd/get_test_command.py +68 -0
- pdd/git_update.py +70 -19
- pdd/incremental_code_generator.py +2 -2
- pdd/insert_includes.py +11 -3
- pdd/llm_invoke.py +1269 -103
- pdd/load_prompt_template.py +36 -10
- pdd/pdd_completion.fish +25 -2
- pdd/pdd_completion.sh +30 -4
- pdd/pdd_completion.zsh +79 -4
- pdd/postprocess.py +10 -3
- pdd/preprocess.py +228 -15
- pdd/preprocess_main.py +8 -5
- pdd/prompts/agentic_crash_explore_LLM.prompt +49 -0
- pdd/prompts/agentic_fix_explore_LLM.prompt +45 -0
- pdd/prompts/agentic_fix_harvest_only_LLM.prompt +48 -0
- pdd/prompts/agentic_fix_primary_LLM.prompt +85 -0
- pdd/prompts/agentic_update_LLM.prompt +1071 -0
- pdd/prompts/agentic_verify_explore_LLM.prompt +45 -0
- pdd/prompts/auto_include_LLM.prompt +100 -905
- pdd/prompts/detect_change_LLM.prompt +122 -20
- pdd/prompts/example_generator_LLM.prompt +22 -1
- pdd/prompts/extract_code_LLM.prompt +5 -1
- pdd/prompts/extract_program_code_fix_LLM.prompt +7 -1
- pdd/prompts/extract_prompt_update_LLM.prompt +7 -8
- pdd/prompts/extract_promptline_LLM.prompt +17 -11
- pdd/prompts/find_verification_errors_LLM.prompt +6 -0
- pdd/prompts/fix_code_module_errors_LLM.prompt +4 -2
- pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +8 -0
- pdd/prompts/fix_verification_errors_LLM.prompt +22 -0
- pdd/prompts/generate_test_LLM.prompt +21 -6
- pdd/prompts/increase_tests_LLM.prompt +1 -5
- pdd/prompts/insert_includes_LLM.prompt +228 -108
- pdd/prompts/trace_LLM.prompt +25 -22
- pdd/prompts/unfinished_prompt_LLM.prompt +85 -1
- pdd/prompts/update_prompt_LLM.prompt +22 -1
- pdd/pytest_output.py +127 -12
- pdd/render_mermaid.py +236 -0
- pdd/setup_tool.py +648 -0
- pdd/simple_math.py +2 -0
- pdd/split_main.py +3 -2
- pdd/summarize_directory.py +49 -6
- pdd/sync_determine_operation.py +543 -98
- pdd/sync_main.py +81 -31
- pdd/sync_orchestration.py +1334 -751
- pdd/sync_tui.py +848 -0
- pdd/template_registry.py +264 -0
- pdd/templates/architecture/architecture_json.prompt +242 -0
- pdd/templates/generic/generate_prompt.prompt +174 -0
- pdd/trace.py +168 -12
- pdd/trace_main.py +4 -3
- pdd/track_cost.py +151 -61
- pdd/unfinished_prompt.py +49 -3
- pdd/update_main.py +549 -67
- pdd/update_model_costs.py +2 -2
- pdd/update_prompt.py +19 -4
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/METADATA +19 -6
- pdd_cli-0.0.90.dist-info/RECORD +153 -0
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/licenses/LICENSE +1 -1
- pdd_cli-0.0.45.dist-info/RECORD +0 -116
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/top_level.txt +0 -0
pdd/fix_verification_errors.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import re
|
|
2
1
|
from typing import Dict, Any, Optional
|
|
3
2
|
from rich import print as rprint
|
|
4
3
|
from rich.markdown import Markdown
|
|
@@ -145,6 +144,7 @@ def fix_verification_errors(
|
|
|
145
144
|
verification_result_obj = verification_response.get('result')
|
|
146
145
|
|
|
147
146
|
if isinstance(verification_result_obj, VerificationOutput):
|
|
147
|
+
# llm_invoke handles all parsing when output_pydantic is specified
|
|
148
148
|
verification_issues_count = verification_result_obj.issues_count
|
|
149
149
|
verification_details = verification_result_obj.details
|
|
150
150
|
if verbose:
|
|
@@ -162,66 +162,18 @@ def fix_verification_errors(
|
|
|
162
162
|
if verbose:
|
|
163
163
|
rprint(f"\n[yellow]Found {verification_issues_count} potential issues. Proceeding to fix step.[/yellow]")
|
|
164
164
|
else:
|
|
165
|
-
rprint(f"[yellow]Warning:[/yellow]
|
|
165
|
+
rprint(f"[yellow]Warning:[/yellow] issues_count is {verification_issues_count}, but details field is empty or missing. Treating as no actionable issues found.")
|
|
166
166
|
verification_issues_count = 0
|
|
167
167
|
else:
|
|
168
168
|
if verbose:
|
|
169
169
|
rprint("\n[green]No issues found during verification based on structured output.[/green]")
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
parsed_issues_count = int(issues_match.group(1))
|
|
175
|
-
details_match = re.search(r'<details>(.*?)</details>', verification_result_obj, re.DOTALL)
|
|
176
|
-
parsed_verification_details = details_match.group(1).strip() if (details_match and details_match.group(1)) else None
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if parsed_issues_count > 0:
|
|
180
|
-
if parsed_verification_details: # Check if details exist and are not empty
|
|
181
|
-
issues_found = True
|
|
182
|
-
verification_issues_count = parsed_issues_count
|
|
183
|
-
verification_details = parsed_verification_details
|
|
184
|
-
if verbose:
|
|
185
|
-
rprint(f"\n[yellow]Found {verification_issues_count} potential issues in string response. Proceeding to fix step.[/yellow]")
|
|
186
|
-
else:
|
|
187
|
-
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.")
|
|
188
|
-
verification_issues_count = 0
|
|
189
|
-
issues_found = False
|
|
190
|
-
else: # parsed_issues_count == 0
|
|
191
|
-
verification_issues_count = 0
|
|
192
|
-
issues_found = False
|
|
193
|
-
if verbose:
|
|
194
|
-
rprint("\n[green]No issues found in string verification based on <issues_count> being 0.[/green]")
|
|
195
|
-
else: # issues_match is None (tag not found or content not digits)
|
|
196
|
-
rprint("[bold red]Error:[/bold red] Could not find or parse integer value from <issues_count> tag in string response.")
|
|
197
|
-
return {
|
|
198
|
-
"explanation": None,
|
|
199
|
-
"fixed_program": program,
|
|
200
|
-
"fixed_code": code,
|
|
201
|
-
"total_cost": total_cost,
|
|
202
|
-
"model_name": model_name,
|
|
203
|
-
"verification_issues_count": 0,
|
|
204
|
-
}
|
|
205
|
-
except ValueError: # Should not be hit if regex is \d+, but as a safeguard
|
|
206
|
-
rprint("[bold red]Error:[/bold red] Invalid non-integer value in <issues_count> tag in string response.")
|
|
207
|
-
return {
|
|
208
|
-
"explanation": None,
|
|
209
|
-
"fixed_program": program,
|
|
210
|
-
"fixed_code": code,
|
|
211
|
-
"total_cost": total_cost,
|
|
212
|
-
"model_name": model_name,
|
|
213
|
-
"verification_issues_count": 0,
|
|
214
|
-
}
|
|
215
|
-
else: # Not VerificationOutput and not a successfully parsed string
|
|
216
|
-
rprint("[bold red]Error:[/bold red] Verification LLM call did not return the expected structured output (e.g., parsing failed).")
|
|
217
|
-
rprint(f" [dim]Expected type:[/dim] {VerificationOutput} or str")
|
|
170
|
+
else:
|
|
171
|
+
# llm_invoke should always return VerificationOutput when output_pydantic is specified
|
|
172
|
+
rprint("[bold red]Error:[/bold red] Verification LLM call did not return the expected structured output.")
|
|
173
|
+
rprint(f" [dim]Expected type:[/dim] {VerificationOutput}")
|
|
218
174
|
rprint(f" [dim]Received type:[/dim] {type(verification_result_obj)}")
|
|
219
175
|
content_str = str(verification_result_obj)
|
|
220
176
|
rprint(f" [dim]Received content:[/dim] {content_str[:500]}{'...' if len(content_str) > 500 else ''}")
|
|
221
|
-
raw_text = verification_response.get('result_text')
|
|
222
|
-
if raw_text:
|
|
223
|
-
raw_text_str = str(raw_text)
|
|
224
|
-
rprint(f" [dim]Raw LLM text (if available from llm_invoke):[/dim] {raw_text_str[:500]}{'...' if len(raw_text_str) > 500 else ''}")
|
|
225
177
|
return {
|
|
226
178
|
"explanation": None,
|
|
227
179
|
"fixed_program": program,
|
|
@@ -262,63 +214,23 @@ def fix_verification_errors(
|
|
|
262
214
|
rprint(f" [dim]Cost:[/dim] ${fix_response.get('cost', 0.0):.6f}")
|
|
263
215
|
|
|
264
216
|
fix_result_obj = fix_response.get('result')
|
|
265
|
-
parsed_fix_successfully = False
|
|
266
217
|
|
|
267
218
|
if isinstance(fix_result_obj, FixerOutput):
|
|
219
|
+
# llm_invoke handles all parsing and unescaping via _unescape_code_newlines
|
|
268
220
|
fixed_program = fix_result_obj.fixed_program
|
|
269
221
|
fixed_code = fix_result_obj.fixed_code
|
|
270
222
|
fix_explanation = fix_result_obj.explanation
|
|
271
|
-
|
|
272
|
-
# Unescape literal \n strings to actual newlines
|
|
273
|
-
if fixed_program:
|
|
274
|
-
fixed_program = fixed_program.replace('\\n', '\n')
|
|
275
|
-
if fixed_code:
|
|
276
|
-
fixed_code = fixed_code.replace('\\n', '\n')
|
|
277
|
-
|
|
278
|
-
parsed_fix_successfully = True
|
|
223
|
+
|
|
279
224
|
if verbose:
|
|
280
225
|
rprint("[green]Successfully parsed structured output for fix.[/green]")
|
|
281
226
|
rprint(Markdown(f"**Explanation from LLM:**\n{fix_explanation}"))
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
if program_match or code_match or explanation_match: # If any tag is found, attempt to parse
|
|
288
|
-
fixed_program_candidate = program_match.group(1).strip() if (program_match and program_match.group(1)) else None
|
|
289
|
-
fixed_code_candidate = code_match.group(1).strip() if (code_match and code_match.group(1)) else None
|
|
290
|
-
fix_explanation_candidate = explanation_match.group(1).strip() if (explanation_match and explanation_match.group(1)) else None
|
|
291
|
-
|
|
292
|
-
# Unescape literal \n strings to actual newlines
|
|
293
|
-
if fixed_program_candidate:
|
|
294
|
-
fixed_program_candidate = fixed_program_candidate.replace('\\n', '\n')
|
|
295
|
-
if fixed_code_candidate:
|
|
296
|
-
fixed_code_candidate = fixed_code_candidate.replace('\\n', '\n')
|
|
297
|
-
|
|
298
|
-
fixed_program = fixed_program_candidate if fixed_program_candidate else program
|
|
299
|
-
fixed_code = fixed_code_candidate if fixed_code_candidate else code
|
|
300
|
-
fix_explanation = fix_explanation_candidate if fix_explanation_candidate else "[Fix explanation not provided by LLM]"
|
|
301
|
-
parsed_fix_successfully = True
|
|
302
|
-
|
|
303
|
-
if verbose:
|
|
304
|
-
if not program_match or not fixed_program_candidate:
|
|
305
|
-
rprint("[yellow]Warning:[/yellow] Could not find or parse <fixed_program> tag in fix result string. Using original program.")
|
|
306
|
-
if not code_match or not fixed_code_candidate:
|
|
307
|
-
rprint("[yellow]Warning:[/yellow] Could not find or parse <fixed_code> tag in fix result string. Using original code module.")
|
|
308
|
-
if not explanation_match or not fix_explanation_candidate:
|
|
309
|
-
rprint("[yellow]Warning:[/yellow] Could not find or parse <explanation> tag in fix result string. Using default explanation.")
|
|
310
|
-
# else: string, but no relevant tags. Will fall to parsed_fix_successfully = False below
|
|
311
|
-
|
|
312
|
-
if not parsed_fix_successfully:
|
|
313
|
-
rprint(f"[bold red]Error:[/bold red] Fix generation LLM call did not return the expected structured output (e.g., parsing failed).")
|
|
314
|
-
rprint(f" [dim]Expected type:[/dim] {FixerOutput} or str (with XML tags)")
|
|
227
|
+
else:
|
|
228
|
+
# llm_invoke should always return FixerOutput when output_pydantic is specified
|
|
229
|
+
rprint(f"[bold red]Error:[/bold red] Fix generation LLM call did not return the expected structured output.")
|
|
230
|
+
rprint(f" [dim]Expected type:[/dim] {FixerOutput}")
|
|
315
231
|
rprint(f" [dim]Received type:[/dim] {type(fix_result_obj)}")
|
|
316
232
|
content_str = str(fix_result_obj)
|
|
317
233
|
rprint(f" [dim]Received content:[/dim] {content_str[:500]}{'...' if len(content_str) > 500 else ''}")
|
|
318
|
-
raw_text = fix_response.get('result_text')
|
|
319
|
-
if raw_text:
|
|
320
|
-
raw_text_str = str(raw_text)
|
|
321
|
-
rprint(f" [dim]Raw LLM text (if available from llm_invoke):[/dim] {raw_text_str[:500]}{'...' if len(raw_text_str) > 500 else ''}")
|
|
322
234
|
fix_explanation = "[Error: Failed to parse structured output from LLM for fix explanation]"
|
|
323
235
|
# fixed_program and fixed_code remain original (already initialized)
|
|
324
236
|
|