pdd-cli 0.0.90__py3-none-any.whl → 0.0.118__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.
Files changed (144) hide show
  1. pdd/__init__.py +38 -6
  2. pdd/agentic_bug.py +323 -0
  3. pdd/agentic_bug_orchestrator.py +497 -0
  4. pdd/agentic_change.py +231 -0
  5. pdd/agentic_change_orchestrator.py +526 -0
  6. pdd/agentic_common.py +521 -786
  7. pdd/agentic_e2e_fix.py +319 -0
  8. pdd/agentic_e2e_fix_orchestrator.py +426 -0
  9. pdd/agentic_fix.py +118 -3
  10. pdd/agentic_update.py +25 -8
  11. pdd/architecture_sync.py +565 -0
  12. pdd/auth_service.py +210 -0
  13. pdd/auto_deps_main.py +63 -53
  14. pdd/auto_include.py +185 -3
  15. pdd/auto_update.py +125 -47
  16. pdd/bug_main.py +195 -23
  17. pdd/cmd_test_main.py +345 -197
  18. pdd/code_generator.py +4 -2
  19. pdd/code_generator_main.py +118 -32
  20. pdd/commands/__init__.py +6 -0
  21. pdd/commands/analysis.py +87 -29
  22. pdd/commands/auth.py +309 -0
  23. pdd/commands/connect.py +290 -0
  24. pdd/commands/fix.py +136 -113
  25. pdd/commands/maintenance.py +3 -2
  26. pdd/commands/misc.py +8 -0
  27. pdd/commands/modify.py +190 -164
  28. pdd/commands/sessions.py +284 -0
  29. pdd/construct_paths.py +334 -32
  30. pdd/context_generator_main.py +167 -170
  31. pdd/continue_generation.py +6 -3
  32. pdd/core/__init__.py +33 -0
  33. pdd/core/cli.py +27 -3
  34. pdd/core/cloud.py +237 -0
  35. pdd/core/errors.py +4 -0
  36. pdd/core/remote_session.py +61 -0
  37. pdd/crash_main.py +219 -23
  38. pdd/data/llm_model.csv +4 -4
  39. pdd/docs/prompting_guide.md +864 -0
  40. pdd/docs/whitepaper_with_benchmarks/data_and_functions/benchmark_analysis.py +495 -0
  41. pdd/docs/whitepaper_with_benchmarks/data_and_functions/creation_compare.py +528 -0
  42. pdd/fix_code_loop.py +208 -34
  43. pdd/fix_code_module_errors.py +6 -2
  44. pdd/fix_error_loop.py +291 -38
  45. pdd/fix_main.py +204 -4
  46. pdd/fix_verification_errors_loop.py +235 -26
  47. pdd/fix_verification_main.py +269 -83
  48. pdd/frontend/dist/assets/index-B5DZHykP.css +1 -0
  49. pdd/frontend/dist/assets/index-DQ3wkeQ2.js +449 -0
  50. pdd/frontend/dist/index.html +376 -0
  51. pdd/frontend/dist/logo.svg +33 -0
  52. pdd/generate_output_paths.py +46 -5
  53. pdd/generate_test.py +212 -151
  54. pdd/get_comment.py +19 -44
  55. pdd/get_extension.py +8 -9
  56. pdd/get_jwt_token.py +309 -20
  57. pdd/get_language.py +8 -7
  58. pdd/get_run_command.py +7 -5
  59. pdd/insert_includes.py +2 -1
  60. pdd/llm_invoke.py +459 -95
  61. pdd/load_prompt_template.py +15 -34
  62. pdd/path_resolution.py +140 -0
  63. pdd/postprocess.py +4 -1
  64. pdd/preprocess.py +68 -12
  65. pdd/preprocess_main.py +33 -1
  66. pdd/prompts/agentic_bug_step10_pr_LLM.prompt +182 -0
  67. pdd/prompts/agentic_bug_step1_duplicate_LLM.prompt +73 -0
  68. pdd/prompts/agentic_bug_step2_docs_LLM.prompt +129 -0
  69. pdd/prompts/agentic_bug_step3_triage_LLM.prompt +95 -0
  70. pdd/prompts/agentic_bug_step4_reproduce_LLM.prompt +97 -0
  71. pdd/prompts/agentic_bug_step5_root_cause_LLM.prompt +123 -0
  72. pdd/prompts/agentic_bug_step6_test_plan_LLM.prompt +107 -0
  73. pdd/prompts/agentic_bug_step7_generate_LLM.prompt +172 -0
  74. pdd/prompts/agentic_bug_step8_verify_LLM.prompt +119 -0
  75. pdd/prompts/agentic_bug_step9_e2e_test_LLM.prompt +289 -0
  76. pdd/prompts/agentic_change_step10_identify_issues_LLM.prompt +1006 -0
  77. pdd/prompts/agentic_change_step11_fix_issues_LLM.prompt +984 -0
  78. pdd/prompts/agentic_change_step12_create_pr_LLM.prompt +131 -0
  79. pdd/prompts/agentic_change_step1_duplicate_LLM.prompt +73 -0
  80. pdd/prompts/agentic_change_step2_docs_LLM.prompt +101 -0
  81. pdd/prompts/agentic_change_step3_research_LLM.prompt +126 -0
  82. pdd/prompts/agentic_change_step4_clarify_LLM.prompt +164 -0
  83. pdd/prompts/agentic_change_step5_docs_change_LLM.prompt +981 -0
  84. pdd/prompts/agentic_change_step6_devunits_LLM.prompt +1005 -0
  85. pdd/prompts/agentic_change_step7_architecture_LLM.prompt +1044 -0
  86. pdd/prompts/agentic_change_step8_analyze_LLM.prompt +1027 -0
  87. pdd/prompts/agentic_change_step9_implement_LLM.prompt +1077 -0
  88. pdd/prompts/agentic_e2e_fix_step1_unit_tests_LLM.prompt +90 -0
  89. pdd/prompts/agentic_e2e_fix_step2_e2e_tests_LLM.prompt +91 -0
  90. pdd/prompts/agentic_e2e_fix_step3_root_cause_LLM.prompt +89 -0
  91. pdd/prompts/agentic_e2e_fix_step4_fix_e2e_tests_LLM.prompt +96 -0
  92. pdd/prompts/agentic_e2e_fix_step5_identify_devunits_LLM.prompt +91 -0
  93. pdd/prompts/agentic_e2e_fix_step6_create_unit_tests_LLM.prompt +106 -0
  94. pdd/prompts/agentic_e2e_fix_step7_verify_tests_LLM.prompt +116 -0
  95. pdd/prompts/agentic_e2e_fix_step8_run_pdd_fix_LLM.prompt +120 -0
  96. pdd/prompts/agentic_e2e_fix_step9_verify_all_LLM.prompt +146 -0
  97. pdd/prompts/agentic_fix_primary_LLM.prompt +2 -2
  98. pdd/prompts/agentic_update_LLM.prompt +192 -338
  99. pdd/prompts/auto_include_LLM.prompt +22 -0
  100. pdd/prompts/change_LLM.prompt +3093 -1
  101. pdd/prompts/detect_change_LLM.prompt +571 -14
  102. pdd/prompts/fix_code_module_errors_LLM.prompt +8 -0
  103. pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +1 -0
  104. pdd/prompts/generate_test_LLM.prompt +20 -1
  105. pdd/prompts/generate_test_from_example_LLM.prompt +115 -0
  106. pdd/prompts/insert_includes_LLM.prompt +262 -252
  107. pdd/prompts/prompt_code_diff_LLM.prompt +119 -0
  108. pdd/prompts/prompt_diff_LLM.prompt +82 -0
  109. pdd/remote_session.py +876 -0
  110. pdd/server/__init__.py +52 -0
  111. pdd/server/app.py +335 -0
  112. pdd/server/click_executor.py +587 -0
  113. pdd/server/executor.py +338 -0
  114. pdd/server/jobs.py +661 -0
  115. pdd/server/models.py +241 -0
  116. pdd/server/routes/__init__.py +31 -0
  117. pdd/server/routes/architecture.py +451 -0
  118. pdd/server/routes/auth.py +364 -0
  119. pdd/server/routes/commands.py +929 -0
  120. pdd/server/routes/config.py +42 -0
  121. pdd/server/routes/files.py +603 -0
  122. pdd/server/routes/prompts.py +1322 -0
  123. pdd/server/routes/websocket.py +473 -0
  124. pdd/server/security.py +243 -0
  125. pdd/server/terminal_spawner.py +209 -0
  126. pdd/server/token_counter.py +222 -0
  127. pdd/summarize_directory.py +236 -237
  128. pdd/sync_animation.py +8 -4
  129. pdd/sync_determine_operation.py +329 -47
  130. pdd/sync_main.py +272 -28
  131. pdd/sync_orchestration.py +136 -75
  132. pdd/template_expander.py +161 -0
  133. pdd/templates/architecture/architecture_json.prompt +41 -46
  134. pdd/trace.py +1 -1
  135. pdd/track_cost.py +0 -13
  136. pdd/unfinished_prompt.py +2 -1
  137. pdd/update_main.py +23 -5
  138. {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/METADATA +15 -10
  139. pdd_cli-0.0.118.dist-info/RECORD +227 -0
  140. pdd_cli-0.0.90.dist-info/RECORD +0 -153
  141. {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/WHEEL +0 -0
  142. {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/entry_points.txt +0 -0
  143. {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/licenses/LICENSE +0 -0
  144. {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/top_level.txt +0 -0
pdd/fix_code_loop.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from __future__ import annotations
2
+ import json
2
3
  import os
3
4
  import shutil
4
5
  import subprocess
@@ -7,6 +8,8 @@ import threading
7
8
  from pathlib import Path
8
9
  from typing import Tuple, Optional, Union, List
9
10
 
11
+ import requests
12
+
10
13
  # Try to import DEFAULT_TIME, with fallback
11
14
  try:
12
15
  from . import DEFAULT_TIME
@@ -91,6 +94,83 @@ except ImportError:
91
94
  def rprint(*args, **kwargs):
92
95
  print(*args)
93
96
 
97
+ # Cloud configuration
98
+ try:
99
+ from .core.cloud import CloudConfig
100
+ CLOUD_AVAILABLE = True
101
+ except ImportError:
102
+ CLOUD_AVAILABLE = False
103
+ CloudConfig = None
104
+
105
+ # Cloud request timeout for crash fix
106
+ CLOUD_REQUEST_TIMEOUT = 400 # seconds
107
+
108
+ def cloud_crash_fix(
109
+ program: str,
110
+ prompt: str,
111
+ code: str,
112
+ errors: str,
113
+ strength: float,
114
+ temperature: float,
115
+ time: float,
116
+ verbose: bool,
117
+ program_path: str = "",
118
+ code_path: str = "",
119
+ language: str = "python",
120
+ ) -> Tuple[bool, bool, str, str, str, float, Optional[str]]:
121
+ """
122
+ Call cloud crashCode endpoint for LLM crash fix.
123
+
124
+ Returns:
125
+ Tuple of (update_program, update_code, fixed_program, fixed_code, analysis, cost, model_name)
126
+ """
127
+ if not CLOUD_AVAILABLE or CloudConfig is None:
128
+ raise RuntimeError("Cloud configuration not available")
129
+
130
+ jwt_token = CloudConfig.get_jwt_token(verbose=verbose)
131
+ if not jwt_token:
132
+ raise RuntimeError("Cloud authentication failed - no JWT token")
133
+
134
+ payload = {
135
+ "programContent": program,
136
+ "promptContent": prompt,
137
+ "codeContent": code,
138
+ "errorContent": errors,
139
+ "language": language,
140
+ "strength": strength,
141
+ "temperature": temperature,
142
+ "time": time if time is not None else 0.25,
143
+ "verbose": verbose,
144
+ "programPath": program_path,
145
+ "codePath": code_path,
146
+ }
147
+
148
+ headers = {
149
+ "Authorization": f"Bearer {jwt_token}",
150
+ "Content-Type": "application/json"
151
+ }
152
+ cloud_url = CloudConfig.get_endpoint_url("crashCode")
153
+
154
+ response = requests.post(
155
+ cloud_url,
156
+ json=payload,
157
+ headers=headers,
158
+ timeout=CLOUD_REQUEST_TIMEOUT
159
+ )
160
+ response.raise_for_status()
161
+
162
+ response_data = response.json()
163
+ fixed_code = response_data.get("fixedCode", "")
164
+ fixed_program = response_data.get("fixedProgram", "")
165
+ update_code = response_data.get("updateCode", False)
166
+ update_program = response_data.get("updateProgram", False)
167
+ analysis = response_data.get("analysis", "")
168
+ cost = float(response_data.get("totalCost", 0.0))
169
+ model_name = response_data.get("modelName", "cloud_model")
170
+
171
+ return update_program, update_code, fixed_program, fixed_code, analysis, cost, model_name
172
+
173
+
94
174
  # Use relative import for internal modules
95
175
  try:
96
176
  from .fix_code_module_errors import fix_code_module_errors
@@ -173,22 +253,30 @@ def run_process_with_output(cmd_args, timeout=300):
173
253
  except Exception:
174
254
  pass
175
255
 
176
- # Close pipes to unblock reader threads
177
- try:
178
- proc.stdout.close()
179
- except Exception:
180
- pass
181
- try:
182
- proc.stderr.close()
183
- except Exception:
184
- pass
256
+ # Wait for threads to finish reading with timeout
257
+ # For normal completion, threads will exit when they read EOF from the pipe
258
+ # For timeout/kill cases, we may need to close pipes to unblock them
259
+ THREAD_JOIN_TIMEOUT = 5 # seconds - enough time to drain normal output buffers
185
260
 
186
- # Wait for threads with timeout to prevent indefinite hangs
187
- THREAD_JOIN_TIMEOUT = 5 # seconds
188
261
  t_out.join(timeout=THREAD_JOIN_TIMEOUT)
189
262
  t_err.join(timeout=THREAD_JOIN_TIMEOUT)
190
263
 
191
- # If threads are still alive after timeout, log it (they're daemon threads so won't block exit)
264
+ # If threads are still alive after first timeout, close pipes to unblock them
265
+ # This handles cases where child processes keep pipes open
266
+ if t_out.is_alive() or t_err.is_alive():
267
+ try:
268
+ proc.stdout.close()
269
+ except Exception:
270
+ pass
271
+ try:
272
+ proc.stderr.close()
273
+ except Exception:
274
+ pass
275
+ # Give threads a bit more time after closing pipes
276
+ t_out.join(timeout=2)
277
+ t_err.join(timeout=2)
278
+
279
+ # If threads are still alive after all attempts, log it
192
280
  if t_out.is_alive() or t_err.is_alive():
193
281
  captured_stderr.append(b"\n[Thread join timeout - some output may be lost]\n")
194
282
 
@@ -211,10 +299,16 @@ def fix_code_loop(
211
299
  time: float = DEFAULT_TIME,
212
300
  prompt_file: str = "",
213
301
  agentic_fallback: bool = True,
302
+ use_cloud: bool = False,
214
303
  ) -> Tuple[bool, str, str, int, float, Optional[str]]:
215
304
  """
216
305
  Attempts to fix errors in a code module through multiple iterations.
217
306
 
307
+ Hybrid Cloud Support:
308
+ When use_cloud=True, the LLM fix calls are routed to the cloud crashCode endpoint
309
+ while local verification program execution stays local. This allows the loop to
310
+ pass local verification results to the cloud for analysis and fixes.
311
+
218
312
  Args:
219
313
  code_file: Path to the code file being tested.
220
314
  prompt: The prompt that generated the code under test.
@@ -228,6 +322,7 @@ def fix_code_loop(
228
322
  time: Time limit for the LLM calls (default: DEFAULT_TIME).
229
323
  prompt_file: Path to the prompt file.
230
324
  agentic_fallback: Enable agentic fallback if the primary fix mechanism fails.
325
+ use_cloud: If True, use cloud LLM for fix calls while keeping verification execution local.
231
326
 
232
327
  Returns:
233
328
  Tuple containing the following in order:
@@ -257,7 +352,37 @@ def fix_code_loop(
257
352
  lang = get_language(os.path.splitext(code_file)[1])
258
353
  verify_cmd = default_verify_cmd_for(lang, verification_program)
259
354
  if not verify_cmd:
260
- raise ValueError(f"No default verification command for language: {lang}")
355
+ # No verify command available (e.g., Java without maven/gradle).
356
+ # Trigger agentic fallback directly using any existing error log.
357
+ rprint(f"[cyan]No verification command for {lang}. Triggering agentic fallback directly...[/cyan]")
358
+ error_log_path = Path(error_log_file)
359
+ error_log_path.parent.mkdir(parents=True, exist_ok=True)
360
+ # Read existing error content or create minimal log
361
+ if not error_log_path.exists() or error_log_path.stat().st_size == 0:
362
+ with open(error_log_path, "w") as f:
363
+ f.write(f"No verification command available for language: {lang}\n")
364
+ f.write("Agentic fix will attempt to resolve the issue.\n")
365
+
366
+ success, _msg, agent_cost, agent_model, agent_changed_files = _safe_run_agentic_crash(
367
+ prompt_file=prompt_file,
368
+ code_file=code_file,
369
+ program_file=verification_program,
370
+ crash_log_file=error_log_file,
371
+ cwd=Path(prompt_file).parent if prompt_file else None
372
+ )
373
+ final_program = ""
374
+ final_code = ""
375
+ try:
376
+ with open(verification_program, "r") as f:
377
+ final_program = f.read()
378
+ except Exception:
379
+ pass
380
+ try:
381
+ with open(code_file, "r") as f:
382
+ final_code = f.read()
383
+ except Exception:
384
+ pass
385
+ return success, final_program, final_code, 1, agent_cost, agent_model
261
386
 
262
387
  verify_result = subprocess.run(verify_cmd, capture_output=True, text=True, shell=True)
263
388
  pytest_output = (verify_result.stdout or "") + "\n" + (verify_result.stderr or "")
@@ -320,10 +445,17 @@ def fix_code_loop(
320
445
  history_log = "<history>\n"
321
446
 
322
447
  # Create initial backups before any modifications
448
+ # Store in .pdd/backups/ to avoid polluting code/test directories
449
+ from datetime import datetime
450
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
323
451
  code_file_path = Path(code_file)
324
452
  verification_program_path = Path(verification_program)
325
- original_code_backup = f"{code_file_path.stem}_original_backup{code_file_path.suffix}"
326
- original_program_backup = f"{verification_program_path.stem}_original_backup{verification_program_path.suffix}"
453
+
454
+ backup_dir = Path.cwd() / '.pdd' / 'backups' / code_file_path.stem / timestamp
455
+ backup_dir.mkdir(parents=True, exist_ok=True)
456
+
457
+ original_code_backup = str(backup_dir / f"code_original{code_file_path.suffix}")
458
+ original_program_backup = str(backup_dir / f"program_original{verification_program_path.suffix}")
327
459
 
328
460
  try:
329
461
  shutil.copy2(code_file, original_code_backup)
@@ -411,10 +543,9 @@ def fix_code_loop(
411
543
 
412
544
 
413
545
  # Create backup copies for this iteration BEFORE calling LLM
414
- code_base, code_ext = os.path.splitext(code_file)
415
- program_base, program_ext = os.path.splitext(verification_program)
416
- code_backup_path = f"{code_base}_{current_iteration_number}{code_ext}"
417
- program_backup_path = f"{program_base}_{current_iteration_number}{program_ext}"
546
+ # Store in .pdd/backups/ (backup_dir already created above)
547
+ code_backup_path = str(backup_dir / f"code_{current_iteration_number}{code_file_path.suffix}")
548
+ program_backup_path = str(backup_dir / f"program_{current_iteration_number}{verification_program_path.suffix}")
418
549
 
419
550
  try:
420
551
  shutil.copy2(code_file, code_backup_path)
@@ -439,7 +570,7 @@ def fix_code_loop(
439
570
  # Temporarily close the XML structure for the LLM call
440
571
  error_context_for_llm = history_log + attempt_log_entry + " </attempt>\n</history>\n"
441
572
 
442
- # Call fix_code_module_errors
573
+ # Call fix (cloud or local based on use_cloud parameter)
443
574
  rprint("Attempting to fix errors using LLM...")
444
575
  update_program, update_code, fixed_program, fixed_code = False, False, "", ""
445
576
  program_code_fix, cost, model_name_iter = "", 0.0, None
@@ -449,20 +580,63 @@ def fix_code_loop(
449
580
  # For simplicity, we assume fix_code_module_errors prints directly using `rprint`
450
581
 
451
582
  try:
452
- # Note: The example signature for fix_code_module_errors returns 7 values
453
- (update_program, update_code, fixed_program, fixed_code,
454
- program_code_fix, cost, model_name_iter) = fix_code_module_errors(
455
- program=current_program,
456
- prompt=prompt,
457
- code=current_code,
458
- errors=error_context_for_llm, # Pass the structured history
459
- strength=strength,
460
- temperature=temperature,
461
- time=time, # Pass time
462
- verbose=verbose,
463
- )
464
- if model_name_iter:
465
- model_name = model_name_iter # Update model name if returned
583
+ if use_cloud:
584
+ # Use cloud LLM for fix - local verification results passed via error_context_for_llm
585
+ try:
586
+ (update_program, update_code, fixed_program, fixed_code,
587
+ program_code_fix, cost, model_name_iter) = cloud_crash_fix(
588
+ program=current_program,
589
+ prompt=prompt,
590
+ code=current_code,
591
+ errors=error_context_for_llm,
592
+ strength=strength,
593
+ temperature=temperature,
594
+ time=time,
595
+ verbose=verbose,
596
+ program_path=verification_program,
597
+ code_path=code_file,
598
+ language="python" if is_python else get_language(os.path.splitext(code_file)[1]),
599
+ )
600
+ if model_name_iter:
601
+ model_name = model_name_iter
602
+ if verbose:
603
+ rprint(f"[cyan]Cloud crash fix completed. Cost: ${cost:.4f}[/cyan]")
604
+ except (requests.exceptions.RequestException, RuntimeError) as cloud_err:
605
+ # Cloud failed - fall back to local
606
+ rprint(f"[yellow]Cloud crash fix failed: {cloud_err}. Falling back to local.[/yellow]")
607
+ (update_program, update_code, fixed_program, fixed_code,
608
+ program_code_fix, cost, model_name_iter) = fix_code_module_errors(
609
+ program=current_program,
610
+ prompt=prompt,
611
+ code=current_code,
612
+ errors=error_context_for_llm,
613
+ strength=strength,
614
+ temperature=temperature,
615
+ time=time,
616
+ verbose=verbose,
617
+ program_path=verification_program,
618
+ code_path=code_file,
619
+ )
620
+ if model_name_iter:
621
+ model_name = model_name_iter
622
+ else:
623
+ # Local LLM fix
624
+ # Note: The example signature for fix_code_module_errors returns 7 values
625
+ (update_program, update_code, fixed_program, fixed_code,
626
+ program_code_fix, cost, model_name_iter) = fix_code_module_errors(
627
+ program=current_program,
628
+ prompt=prompt,
629
+ code=current_code,
630
+ errors=error_context_for_llm, # Pass the structured history
631
+ strength=strength,
632
+ temperature=temperature,
633
+ time=time, # Pass time
634
+ verbose=verbose,
635
+ program_path=verification_program, # Pass file path for LLM context
636
+ code_path=code_file, # Pass file path for LLM context
637
+ )
638
+ if model_name_iter:
639
+ model_name = model_name_iter # Update model name if returned
466
640
 
467
641
  except Exception as e:
468
642
  rprint(f"[bold red]Error calling fix_code_module_errors: {e}[/bold red]")
@@ -38,7 +38,9 @@ def fix_code_module_errors(
38
38
  strength: float = DEFAULT_STRENGTH,
39
39
  temperature: float = 0,
40
40
  time: float = DEFAULT_TIME,
41
- verbose: bool = False
41
+ verbose: bool = False,
42
+ program_path: str = "",
43
+ code_path: str = "",
42
44
  ) -> Tuple[bool, bool, str, str, str, float, str]:
43
45
  """
44
46
  Fix errors in a code module that caused a program to crash and/or have errors.
@@ -62,7 +64,9 @@ def fix_code_module_errors(
62
64
  "program": program,
63
65
  "prompt": prompt,
64
66
  "code": code,
65
- "errors": errors
67
+ "errors": errors,
68
+ "program_path": program_path,
69
+ "code_path": code_path,
66
70
  }
67
71
 
68
72
  if verbose: