pdd-cli 0.0.45__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 (195) hide show
  1. pdd/__init__.py +40 -8
  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 +598 -0
  7. pdd/agentic_crash.py +534 -0
  8. pdd/agentic_e2e_fix.py +319 -0
  9. pdd/agentic_e2e_fix_orchestrator.py +426 -0
  10. pdd/agentic_fix.py +1294 -0
  11. pdd/agentic_langtest.py +162 -0
  12. pdd/agentic_update.py +387 -0
  13. pdd/agentic_verify.py +183 -0
  14. pdd/architecture_sync.py +565 -0
  15. pdd/auth_service.py +210 -0
  16. pdd/auto_deps_main.py +71 -51
  17. pdd/auto_include.py +245 -5
  18. pdd/auto_update.py +125 -47
  19. pdd/bug_main.py +196 -23
  20. pdd/bug_to_unit_test.py +2 -0
  21. pdd/change_main.py +11 -4
  22. pdd/cli.py +22 -1181
  23. pdd/cmd_test_main.py +350 -150
  24. pdd/code_generator.py +60 -18
  25. pdd/code_generator_main.py +790 -57
  26. pdd/commands/__init__.py +48 -0
  27. pdd/commands/analysis.py +306 -0
  28. pdd/commands/auth.py +309 -0
  29. pdd/commands/connect.py +290 -0
  30. pdd/commands/fix.py +163 -0
  31. pdd/commands/generate.py +257 -0
  32. pdd/commands/maintenance.py +175 -0
  33. pdd/commands/misc.py +87 -0
  34. pdd/commands/modify.py +256 -0
  35. pdd/commands/report.py +144 -0
  36. pdd/commands/sessions.py +284 -0
  37. pdd/commands/templates.py +215 -0
  38. pdd/commands/utility.py +110 -0
  39. pdd/config_resolution.py +58 -0
  40. pdd/conflicts_main.py +8 -3
  41. pdd/construct_paths.py +589 -111
  42. pdd/context_generator.py +10 -2
  43. pdd/context_generator_main.py +175 -76
  44. pdd/continue_generation.py +53 -10
  45. pdd/core/__init__.py +33 -0
  46. pdd/core/cli.py +527 -0
  47. pdd/core/cloud.py +237 -0
  48. pdd/core/dump.py +554 -0
  49. pdd/core/errors.py +67 -0
  50. pdd/core/remote_session.py +61 -0
  51. pdd/core/utils.py +90 -0
  52. pdd/crash_main.py +262 -33
  53. pdd/data/language_format.csv +71 -63
  54. pdd/data/llm_model.csv +20 -18
  55. pdd/detect_change_main.py +5 -4
  56. pdd/docs/prompting_guide.md +864 -0
  57. pdd/docs/whitepaper_with_benchmarks/data_and_functions/benchmark_analysis.py +495 -0
  58. pdd/docs/whitepaper_with_benchmarks/data_and_functions/creation_compare.py +528 -0
  59. pdd/fix_code_loop.py +523 -95
  60. pdd/fix_code_module_errors.py +6 -2
  61. pdd/fix_error_loop.py +491 -92
  62. pdd/fix_errors_from_unit_tests.py +4 -3
  63. pdd/fix_main.py +278 -21
  64. pdd/fix_verification_errors.py +12 -100
  65. pdd/fix_verification_errors_loop.py +529 -286
  66. pdd/fix_verification_main.py +294 -89
  67. pdd/frontend/dist/assets/index-B5DZHykP.css +1 -0
  68. pdd/frontend/dist/assets/index-DQ3wkeQ2.js +449 -0
  69. pdd/frontend/dist/index.html +376 -0
  70. pdd/frontend/dist/logo.svg +33 -0
  71. pdd/generate_output_paths.py +139 -15
  72. pdd/generate_test.py +218 -146
  73. pdd/get_comment.py +19 -44
  74. pdd/get_extension.py +8 -9
  75. pdd/get_jwt_token.py +318 -22
  76. pdd/get_language.py +8 -7
  77. pdd/get_run_command.py +75 -0
  78. pdd/get_test_command.py +68 -0
  79. pdd/git_update.py +70 -19
  80. pdd/incremental_code_generator.py +2 -2
  81. pdd/insert_includes.py +13 -4
  82. pdd/llm_invoke.py +1711 -181
  83. pdd/load_prompt_template.py +19 -12
  84. pdd/path_resolution.py +140 -0
  85. pdd/pdd_completion.fish +25 -2
  86. pdd/pdd_completion.sh +30 -4
  87. pdd/pdd_completion.zsh +79 -4
  88. pdd/postprocess.py +14 -4
  89. pdd/preprocess.py +293 -24
  90. pdd/preprocess_main.py +41 -6
  91. pdd/prompts/agentic_bug_step10_pr_LLM.prompt +182 -0
  92. pdd/prompts/agentic_bug_step1_duplicate_LLM.prompt +73 -0
  93. pdd/prompts/agentic_bug_step2_docs_LLM.prompt +129 -0
  94. pdd/prompts/agentic_bug_step3_triage_LLM.prompt +95 -0
  95. pdd/prompts/agentic_bug_step4_reproduce_LLM.prompt +97 -0
  96. pdd/prompts/agentic_bug_step5_root_cause_LLM.prompt +123 -0
  97. pdd/prompts/agentic_bug_step6_test_plan_LLM.prompt +107 -0
  98. pdd/prompts/agentic_bug_step7_generate_LLM.prompt +172 -0
  99. pdd/prompts/agentic_bug_step8_verify_LLM.prompt +119 -0
  100. pdd/prompts/agentic_bug_step9_e2e_test_LLM.prompt +289 -0
  101. pdd/prompts/agentic_change_step10_identify_issues_LLM.prompt +1006 -0
  102. pdd/prompts/agentic_change_step11_fix_issues_LLM.prompt +984 -0
  103. pdd/prompts/agentic_change_step12_create_pr_LLM.prompt +131 -0
  104. pdd/prompts/agentic_change_step1_duplicate_LLM.prompt +73 -0
  105. pdd/prompts/agentic_change_step2_docs_LLM.prompt +101 -0
  106. pdd/prompts/agentic_change_step3_research_LLM.prompt +126 -0
  107. pdd/prompts/agentic_change_step4_clarify_LLM.prompt +164 -0
  108. pdd/prompts/agentic_change_step5_docs_change_LLM.prompt +981 -0
  109. pdd/prompts/agentic_change_step6_devunits_LLM.prompt +1005 -0
  110. pdd/prompts/agentic_change_step7_architecture_LLM.prompt +1044 -0
  111. pdd/prompts/agentic_change_step8_analyze_LLM.prompt +1027 -0
  112. pdd/prompts/agentic_change_step9_implement_LLM.prompt +1077 -0
  113. pdd/prompts/agentic_crash_explore_LLM.prompt +49 -0
  114. pdd/prompts/agentic_e2e_fix_step1_unit_tests_LLM.prompt +90 -0
  115. pdd/prompts/agentic_e2e_fix_step2_e2e_tests_LLM.prompt +91 -0
  116. pdd/prompts/agentic_e2e_fix_step3_root_cause_LLM.prompt +89 -0
  117. pdd/prompts/agentic_e2e_fix_step4_fix_e2e_tests_LLM.prompt +96 -0
  118. pdd/prompts/agentic_e2e_fix_step5_identify_devunits_LLM.prompt +91 -0
  119. pdd/prompts/agentic_e2e_fix_step6_create_unit_tests_LLM.prompt +106 -0
  120. pdd/prompts/agentic_e2e_fix_step7_verify_tests_LLM.prompt +116 -0
  121. pdd/prompts/agentic_e2e_fix_step8_run_pdd_fix_LLM.prompt +120 -0
  122. pdd/prompts/agentic_e2e_fix_step9_verify_all_LLM.prompt +146 -0
  123. pdd/prompts/agentic_fix_explore_LLM.prompt +45 -0
  124. pdd/prompts/agentic_fix_harvest_only_LLM.prompt +48 -0
  125. pdd/prompts/agentic_fix_primary_LLM.prompt +85 -0
  126. pdd/prompts/agentic_update_LLM.prompt +925 -0
  127. pdd/prompts/agentic_verify_explore_LLM.prompt +45 -0
  128. pdd/prompts/auto_include_LLM.prompt +122 -905
  129. pdd/prompts/change_LLM.prompt +3093 -1
  130. pdd/prompts/detect_change_LLM.prompt +686 -27
  131. pdd/prompts/example_generator_LLM.prompt +22 -1
  132. pdd/prompts/extract_code_LLM.prompt +5 -1
  133. pdd/prompts/extract_program_code_fix_LLM.prompt +7 -1
  134. pdd/prompts/extract_prompt_update_LLM.prompt +7 -8
  135. pdd/prompts/extract_promptline_LLM.prompt +17 -11
  136. pdd/prompts/find_verification_errors_LLM.prompt +6 -0
  137. pdd/prompts/fix_code_module_errors_LLM.prompt +12 -2
  138. pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +9 -0
  139. pdd/prompts/fix_verification_errors_LLM.prompt +22 -0
  140. pdd/prompts/generate_test_LLM.prompt +41 -7
  141. pdd/prompts/generate_test_from_example_LLM.prompt +115 -0
  142. pdd/prompts/increase_tests_LLM.prompt +1 -5
  143. pdd/prompts/insert_includes_LLM.prompt +316 -186
  144. pdd/prompts/prompt_code_diff_LLM.prompt +119 -0
  145. pdd/prompts/prompt_diff_LLM.prompt +82 -0
  146. pdd/prompts/trace_LLM.prompt +25 -22
  147. pdd/prompts/unfinished_prompt_LLM.prompt +85 -1
  148. pdd/prompts/update_prompt_LLM.prompt +22 -1
  149. pdd/pytest_output.py +127 -12
  150. pdd/remote_session.py +876 -0
  151. pdd/render_mermaid.py +236 -0
  152. pdd/server/__init__.py +52 -0
  153. pdd/server/app.py +335 -0
  154. pdd/server/click_executor.py +587 -0
  155. pdd/server/executor.py +338 -0
  156. pdd/server/jobs.py +661 -0
  157. pdd/server/models.py +241 -0
  158. pdd/server/routes/__init__.py +31 -0
  159. pdd/server/routes/architecture.py +451 -0
  160. pdd/server/routes/auth.py +364 -0
  161. pdd/server/routes/commands.py +929 -0
  162. pdd/server/routes/config.py +42 -0
  163. pdd/server/routes/files.py +603 -0
  164. pdd/server/routes/prompts.py +1322 -0
  165. pdd/server/routes/websocket.py +473 -0
  166. pdd/server/security.py +243 -0
  167. pdd/server/terminal_spawner.py +209 -0
  168. pdd/server/token_counter.py +222 -0
  169. pdd/setup_tool.py +648 -0
  170. pdd/simple_math.py +2 -0
  171. pdd/split_main.py +3 -2
  172. pdd/summarize_directory.py +237 -195
  173. pdd/sync_animation.py +8 -4
  174. pdd/sync_determine_operation.py +839 -112
  175. pdd/sync_main.py +351 -57
  176. pdd/sync_orchestration.py +1400 -756
  177. pdd/sync_tui.py +848 -0
  178. pdd/template_expander.py +161 -0
  179. pdd/template_registry.py +264 -0
  180. pdd/templates/architecture/architecture_json.prompt +237 -0
  181. pdd/templates/generic/generate_prompt.prompt +174 -0
  182. pdd/trace.py +168 -12
  183. pdd/trace_main.py +4 -3
  184. pdd/track_cost.py +140 -63
  185. pdd/unfinished_prompt.py +51 -4
  186. pdd/update_main.py +567 -67
  187. pdd/update_model_costs.py +2 -2
  188. pdd/update_prompt.py +19 -4
  189. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.118.dist-info}/METADATA +29 -11
  190. pdd_cli-0.0.118.dist-info/RECORD +227 -0
  191. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.118.dist-info}/licenses/LICENSE +1 -1
  192. pdd_cli-0.0.45.dist-info/RECORD +0 -116
  193. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.118.dist-info}/WHEEL +0 -0
  194. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.118.dist-info}/entry_points.txt +0 -0
  195. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.118.dist-info}/top_level.txt +0 -0
pdd/git_update.py CHANGED
@@ -4,6 +4,8 @@ from rich import print
4
4
  from rich.console import Console
5
5
  from rich.panel import Panel
6
6
  from .update_prompt import update_prompt
7
+ from .agentic_common import get_available_agents
8
+ from .agentic_update import run_agentic_update
7
9
  import git
8
10
  from . import DEFAULT_TIME
9
11
  console = Console()
@@ -14,21 +16,33 @@ def git_update(
14
16
  strength: float,
15
17
  temperature: float,
16
18
  verbose: bool = False,
17
- time: float = DEFAULT_TIME
19
+ time: float = DEFAULT_TIME,
20
+ simple: bool = False,
21
+ quiet: bool = False,
22
+ prompt_file: Optional[str] = None
18
23
  ) -> Tuple[Optional[str], float, str]:
19
24
  """
20
- Read in modified code, restore the prior checked-in version from GitHub,
21
- update the prompt, write back the modified code, and return outputs.
25
+ Read in modified code, restore the prior checked-in version from Git,
26
+ update the prompt (via agentic or legacy path), write back the modified code,
27
+ and return outputs.
22
28
 
23
29
  Args:
24
- input_prompt (str): The prompt that generated the original code.
30
+ input_prompt (str): The prompt TEXT content (not a file path).
25
31
  modified_code_file (str): Filepath of the modified code.
26
32
  strength (float): Strength parameter for the LLM model.
27
33
  temperature (float): Temperature parameter for the LLM model.
34
+ verbose (bool): Enable verbose logging.
35
+ time (float): Time parameter for the LLM model.
36
+ simple (bool): If True, skip agentic and use legacy update_prompt().
37
+ quiet (bool): Suppress non-error logging.
38
+ prompt_file (Optional[str]): Path to prompt file (required for agentic path).
28
39
 
29
40
  Returns:
30
- Tuple[Optional[str], float, str]: Modified prompt, total cost, and model name.
41
+ Tuple[Optional[str], float, str]: Updated prompt content, total cost, and model name.
31
42
  """
43
+ modified_code: Optional[str] = None
44
+ agentic_cost = 0.0
45
+
32
46
  try:
33
47
  # Check if inputs are valid
34
48
  if not input_prompt or not modified_code_file:
@@ -37,26 +51,57 @@ def git_update(
37
51
  if not os.path.exists(modified_code_file):
38
52
  raise FileNotFoundError(f"Modified code file not found: {modified_code_file}")
39
53
 
40
- # Initialize git repository
41
- repo = git.Repo(search_parent_directories=True)
54
+ # Initialize git repository object once
55
+ repo = git.Repo(modified_code_file, search_parent_directories=True)
56
+ repo_root = repo.working_tree_dir
42
57
 
43
58
  # Get the file's relative path to the repo root
44
- repo_root = repo.git.rev_parse("--show-toplevel")
45
59
  relative_path = os.path.relpath(modified_code_file, repo_root)
46
60
 
47
- # Read the modified code
61
+ # Read the modified code FIRST (before any git operations)
48
62
  with open(modified_code_file, 'r') as file:
49
63
  modified_code = file.read()
50
64
 
51
- # Restore the prior checked-in version
65
+ # Restore the prior checked-in version using the relative path
52
66
  repo.git.checkout('HEAD', '--', relative_path)
53
67
 
54
68
  # Read the original input code
55
69
  with open(modified_code_file, 'r') as file:
56
70
  original_input_code = file.read()
57
71
 
58
- # Call update_prompt function
59
- modified_prompt, total_cost, model_name = update_prompt(
72
+ # Routing decision: agentic vs legacy
73
+ use_agentic = (
74
+ not simple
75
+ and prompt_file is not None
76
+ and get_available_agents()
77
+ )
78
+
79
+ if use_agentic:
80
+ # Agentic path
81
+ success, message, agentic_cost, provider, changed_files = run_agentic_update(
82
+ prompt_file=prompt_file,
83
+ code_file=modified_code_file,
84
+ verbose=verbose,
85
+ quiet=quiet
86
+ )
87
+ if success:
88
+ # Read updated prompt content from file
89
+ with open(prompt_file, 'r') as file:
90
+ updated_prompt = file.read()
91
+
92
+ # Pretty print the results
93
+ console.print(Panel.fit(
94
+ f"[bold green]Success (agentic):[/bold green]\n"
95
+ f"Provider: {provider}\n"
96
+ f"Total cost: ${agentic_cost:.6f}\n"
97
+ f"Changed files: {', '.join(changed_files)}"
98
+ ))
99
+
100
+ return updated_prompt, agentic_cost, provider
101
+ # Fall through to legacy on agentic failure
102
+
103
+ # Legacy path
104
+ result_prompt, legacy_cost, model_name = update_prompt(
60
105
  input_prompt=input_prompt,
61
106
  input_code=original_input_code,
62
107
  modified_code=modified_code,
@@ -66,21 +111,27 @@ def git_update(
66
111
  time=time
67
112
  )
68
113
 
69
- # Write back the modified code
70
- with open(modified_code_file, 'w') as file:
71
- file.write(modified_code)
72
-
114
+ total_cost = agentic_cost + legacy_cost
73
115
 
74
116
  # Pretty print the results
75
117
  console.print(Panel.fit(
76
118
  f"[bold green]Success:[/bold green]\n"
77
- f"Modified prompt: {modified_prompt}\n"
119
+ f"Modified prompt: {result_prompt}\n"
78
120
  f"Total cost: ${total_cost:.6f}\n"
79
121
  f"Model name: {model_name}"
80
122
  ))
81
123
 
82
- return modified_prompt, total_cost, model_name
124
+ return result_prompt, total_cost, model_name
83
125
 
84
126
  except Exception as e:
85
127
  console.print(Panel(f"[bold red]Error:[/bold red] {str(e)}", title="Error", expand=False))
86
- return None, 0.0, ""
128
+ return None, agentic_cost, ""
129
+
130
+ finally:
131
+ # Always restore user's modified code to disk before returning
132
+ if modified_code is not None and modified_code_file:
133
+ try:
134
+ with open(modified_code_file, 'w') as file:
135
+ file.write(modified_code)
136
+ except Exception:
137
+ pass # Best effort restoration
@@ -59,8 +59,8 @@ def incremental_code_generator(
59
59
  if not original_prompt or not new_prompt or not existing_code or not language:
60
60
  raise ValueError("All required inputs (original_prompt, new_prompt, existing_code, language) must be provided.")
61
61
 
62
- if not 0 <= strength <= 1 or not 0 <= temperature <= 1 or not 0 <= time <= 1:
63
- raise ValueError("Strength, temperature, and time must be between 0 and 1.")
62
+ if not 0 <= strength <= 1 or not 0 <= temperature <= 2 or not 0 <= time <= 1:
63
+ raise ValueError("Strength and time must be between 0 and 1. Temperature must be between 0 and 2.")
64
64
 
65
65
  try:
66
66
  total_cost = 0.0
pdd/insert_includes.py CHANGED
@@ -1,4 +1,5 @@
1
- from typing import Tuple
1
+ from __future__ import annotations
2
+ from typing import Callable, Optional, Tuple
2
3
  from pathlib import Path
3
4
  from rich import print
4
5
  from pydantic import BaseModel, Field
@@ -16,10 +17,12 @@ def insert_includes(
16
17
  input_prompt: str,
17
18
  directory_path: str,
18
19
  csv_filename: str,
20
+ prompt_filename: Optional[str] = None,
19
21
  strength: float = DEFAULT_STRENGTH,
20
22
  temperature: float = 0.0,
21
23
  time: float = DEFAULT_TIME,
22
- verbose: bool = False
24
+ verbose: bool = False,
25
+ progress_callback: Optional[Callable[[int, int], None]] = None
23
26
  ) -> Tuple[str, str, float, str]:
24
27
  """
25
28
  Determine needed dependencies and insert them into a prompt.
@@ -28,10 +31,14 @@ def insert_includes(
28
31
  input_prompt (str): The prompt to process
29
32
  directory_path (str): Directory path where the prompt file is located
30
33
  csv_filename (str): Name of the CSV file containing dependencies
34
+ prompt_filename (Optional[str]): The prompt filename being processed,
35
+ used to filter out self-referential example files
31
36
  strength (float): Strength parameter for the LLM model
32
37
  temperature (float): Temperature parameter for the LLM model
33
38
  time (float): Time budget for the LLM model
34
39
  verbose (bool, optional): Whether to print detailed information. Defaults to False.
40
+ progress_callback (Optional[Callable[[int, int], None]]): Callback for progress updates.
41
+ Called with (current, total) for each file processed.
35
42
 
36
43
  Returns:
37
44
  Tuple[str, str, float, str]: Tuple containing:
@@ -56,7 +63,7 @@ def insert_includes(
56
63
  except FileNotFoundError:
57
64
  if verbose:
58
65
  print(f"[yellow]CSV file {csv_filename} not found. Creating empty CSV.[/yellow]")
59
- csv_content = "full_path,file_summary,date\n"
66
+ csv_content = "full_path,file_summary,content_hash\n"
60
67
  Path(csv_filename).write_text(csv_content)
61
68
 
62
69
  # Step 3: Preprocess the prompt template
@@ -75,10 +82,12 @@ def insert_includes(
75
82
  input_prompt=input_prompt,
76
83
  directory_path=directory_path,
77
84
  csv_file=csv_content,
85
+ prompt_filename=prompt_filename,
78
86
  strength=strength,
79
87
  temperature=temperature,
80
88
  time=time,
81
- verbose=verbose
89
+ verbose=verbose,
90
+ progress_callback=progress_callback
82
91
  )
83
92
 
84
93
  if verbose: