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/commands/fix.py CHANGED
@@ -1,82 +1,46 @@
1
- """
2
- Fix command.
3
- """
1
+ from __future__ import annotations
2
+
3
+ import sys
4
4
  import click
5
- from typing import Dict, List, Optional, Tuple, Any
5
+ from typing import Optional, Tuple, Any
6
+ from rich.console import Console
6
7
 
8
+ # Relative imports for internal modules
7
9
  from ..fix_main import fix_main
10
+ from ..agentic_e2e_fix import run_agentic_e2e_fix
8
11
  from ..track_cost import track_cost
9
12
  from ..core.errors import handle_error
10
13
 
11
- @click.command("fix")
12
- @click.argument("prompt_file", type=click.Path(exists=True, dir_okay=False))
13
- @click.argument("code_file", type=click.Path(exists=True, dir_okay=False))
14
- @click.argument("unit_test_files", nargs=-1, type=click.Path(exists=True, dir_okay=False))
15
- @click.argument("error_file", type=click.Path(dir_okay=False)) # Allow non-existent for loop mode
16
- @click.option(
17
- "--output-test",
18
- type=click.Path(writable=True),
19
- default=None,
20
- help="Specify where to save the fixed unit test file (file or directory).",
21
- )
22
- @click.option(
23
- "--output-code",
24
- type=click.Path(writable=True),
25
- default=None,
26
- help="Specify where to save the fixed code file (file or directory).",
27
- )
28
- @click.option(
29
- "--output-results",
30
- type=click.Path(writable=True),
31
- default=None,
32
- help="Specify where to save the results log (file or directory).",
33
- )
34
- @click.option(
35
- "--loop",
36
- is_flag=True,
37
- default=False,
38
- help="Enable iterative fixing process."
39
- )
40
- @click.option(
41
- "--verification-program",
42
- type=click.Path(exists=True, dir_okay=False),
43
- default=None,
44
- help="Path to a Python program that verifies the fix.",
45
- )
46
- @click.option(
47
- "--max-attempts",
48
- type=int,
49
- default=3,
50
- show_default=True,
51
- help="Maximum number of fix attempts.",
52
- )
53
- @click.option(
54
- "--budget",
55
- type=float,
56
- default=5.0,
57
- show_default=True,
58
- help="Maximum cost allowed for the fixing process.",
59
- )
60
- @click.option(
61
- "--auto-submit",
62
- is_flag=True,
63
- default=False,
64
- help="Automatically submit the example if all unit tests pass.",
65
- )
66
- @click.option(
67
- "--agentic-fallback/--no-agentic-fallback",
68
- is_flag=True,
69
- default=True,
70
- help="Enable agentic fallback if the primary fix mechanism fails.",
71
- )
14
+ console = Console()
15
+
16
+ @click.command(name="fix")
17
+ @click.argument("args", nargs=-1)
18
+ @click.option("--manual", is_flag=True, help="Use manual mode with explicit file arguments.")
19
+ @click.option("--timeout-adder", type=float, default=0.0, help="Additional seconds to add to each step's timeout (Agentic mode).")
20
+ @click.option("--max-cycles", type=int, default=5, help="Maximum number of outer loop cycles (Agentic mode).")
21
+ @click.option("--resume/--no-resume", default=True, help="Resume from saved state if available (Agentic mode).")
22
+ @click.option("--force", is_flag=True, help="Override branch mismatch safety check (Agentic mode).")
23
+ @click.option("--no-github-state", is_flag=True, help="Disable GitHub issue comment-based state persistence (Agentic mode).")
24
+ @click.option("--output-test", type=click.Path(), help="Specify where to save the fixed unit test file.")
25
+ @click.option("--output-code", type=click.Path(), help="Specify where to save the fixed code file.")
26
+ @click.option("--output-results", type=click.Path(), help="Specify where to save the results log.")
27
+ @click.option("--loop", is_flag=True, help="Enable iterative fixing process.")
28
+ @click.option("--verification-program", type=click.Path(), help="Path to verification program (required for --loop).")
29
+ @click.option("--max-attempts", type=int, default=3, help="Maximum number of fix attempts.")
30
+ @click.option("--budget", type=float, default=5.0, help="Maximum cost allowed for the fixing process.")
31
+ @click.option("--auto-submit", is_flag=True, help="Automatically submit example if tests pass.")
32
+ @click.option("--agentic-fallback/--no-agentic-fallback", default=True, help="Enable agentic fallback in loop mode.")
72
33
  @click.pass_context
73
34
  @track_cost
74
35
  def fix(
75
36
  ctx: click.Context,
76
- prompt_file: str,
77
- code_file: str,
78
- unit_test_files: Tuple[str, ...],
79
- error_file: str,
37
+ args: Tuple[str, ...],
38
+ manual: bool,
39
+ timeout_adder: float,
40
+ max_cycles: int,
41
+ resume: bool,
42
+ force: bool,
43
+ no_github_state: bool,
80
44
  output_test: Optional[str],
81
45
  output_code: Optional[str],
82
46
  output_results: Optional[str],
@@ -86,55 +50,114 @@ def fix(
86
50
  budget: float,
87
51
  auto_submit: bool,
88
52
  agentic_fallback: bool,
89
- ) -> Optional[Tuple[Dict[str, Any], float, str]]:
90
- """Fix code based on a prompt and unit test errors.
53
+ ) -> Optional[Tuple[Any, float, str]]:
54
+ """
55
+ Fix errors in code and unit tests.
91
56
 
92
- Accepts one or more UNIT_TEST_FILES. Each test file is processed separately,
93
- allowing the AI to run and fix tests individually rather than as a concatenated blob.
57
+ Supports two modes:
58
+ 1. Agentic E2E Fix: pdd fix <GITHUB_ISSUE_URL>
59
+ 2. Manual Mode: pdd fix --manual PROMPT_FILE CODE_FILE UNIT_TEST_FILE... ERROR_FILE
94
60
  """
95
61
  try:
96
- all_results: List[Dict[str, Any]] = []
97
- total_cost = 0.0
98
- model_name = ""
62
+ if not args:
63
+ raise click.UsageError("Missing arguments. See 'pdd fix --help'.")
99
64
 
100
- # Process each unit test file separately
101
- for unit_test_file in unit_test_files:
102
- success, fixed_unit_test, fixed_code, attempts, cost, model = fix_main(
103
- ctx=ctx,
104
- prompt_file=prompt_file,
105
- code_file=code_file,
106
- unit_test_file=unit_test_file,
107
- error_file=error_file,
108
- output_test=output_test,
109
- output_code=output_code,
110
- output_results=output_results,
111
- loop=loop,
112
- verification_program=verification_program,
113
- max_attempts=max_attempts,
114
- budget=budget,
115
- auto_submit=auto_submit,
116
- agentic_fallback=agentic_fallback,
65
+ # Determine mode based on first argument
66
+ # If it looks like a URL and --manual is not set, use Agentic mode
67
+ is_url = args[0].startswith("http") or "github.com" in args[0]
68
+
69
+ # --- Agentic E2E Fix Mode ---
70
+ if is_url and not manual:
71
+ if len(args) > 1:
72
+ console.print("[yellow]Warning: Extra arguments ignored in Agentic E2E Fix mode.[/yellow]")
73
+
74
+ issue_url = args[0]
75
+ verbose = ctx.obj.get("verbose", False)
76
+ quiet = ctx.obj.get("quiet", False)
77
+
78
+ # Call the agentic fix workflow
79
+ success, message, cost, model, _ = run_agentic_e2e_fix(
80
+ issue_url=issue_url,
81
+ timeout_adder=timeout_adder,
82
+ max_cycles=max_cycles,
83
+ resume=resume,
84
+ force=force,
85
+ verbose=verbose,
86
+ quiet=quiet,
87
+ use_github_state=not no_github_state
117
88
  )
118
- all_results.append({
119
- "success": success,
120
- "fixed_unit_test": fixed_unit_test,
121
- "fixed_code": fixed_code,
122
- "attempts": attempts,
123
- "unit_test_file": unit_test_file,
124
- })
125
- total_cost += cost
126
- model_name = model
89
+
90
+ if not success:
91
+ console.print(f"[bold red]Agentic fix failed:[/bold red] {message}")
92
+ else:
93
+ console.print(f"[bold green]Agentic fix completed:[/bold green] {message}")
94
+
95
+ return message, cost, model
96
+
97
+ # --- Manual Mode ---
98
+ else:
99
+ # Validate arguments for manual mode
100
+ # Expected structure: PROMPT_FILE CODE_FILE UNIT_TEST_FILE [UNIT_TEST_FILE...] ERROR_FILE
101
+ if len(args) < 4:
102
+ raise click.UsageError(
103
+ "Manual mode requires at least 4 arguments: PROMPT_FILE CODE_FILE UNIT_TEST_FILE... ERROR_FILE"
104
+ )
105
+
106
+ prompt_file = args[0]
107
+ code_file = args[1]
108
+ error_file = args[-1]
109
+ # All arguments between code file and error file are treated as unit test files
110
+ unit_test_files = args[2:-1]
111
+
112
+ total_cost = 0.0
113
+ last_model = "unknown"
114
+ all_success = True
115
+ results_summary = []
116
+
117
+ # Process each unit test file
118
+ for i, test_file in enumerate(unit_test_files):
119
+ if len(unit_test_files) > 1:
120
+ console.print(f"[bold blue]Processing test file {i+1}/{len(unit_test_files)}: {test_file}[/bold blue]")
121
+
122
+ # Call the core fix logic
123
+ # Note: If multiple test files are processed, output_test will overwrite
124
+ # the same location if specified, as per documentation warning.
125
+ success, _, _, _, cost, model = fix_main(
126
+ ctx=ctx,
127
+ prompt_file=prompt_file,
128
+ code_file=code_file,
129
+ unit_test_file=test_file,
130
+ error_file=error_file,
131
+ output_test=output_test,
132
+ output_code=output_code,
133
+ output_results=output_results,
134
+ loop=loop,
135
+ verification_program=verification_program,
136
+ max_attempts=max_attempts,
137
+ budget=budget,
138
+ auto_submit=auto_submit,
139
+ agentic_fallback=agentic_fallback,
140
+ strength=None, # Use context defaults inside fix_main
141
+ temperature=None # Use context defaults inside fix_main
142
+ )
143
+
144
+ total_cost += cost
145
+ last_model = model
146
+ if not success:
147
+ all_success = False
148
+
149
+ status = "Fixed" if success else "Failed"
150
+ results_summary.append(f"{test_file}: {status}")
151
+
152
+ # Construct return message
153
+ summary_str = "\n".join(results_summary)
154
+ if all_success:
155
+ return f"All files processed successfully.\n{summary_str}", total_cost, last_model
156
+ else:
157
+ return f"Some files failed to fix.\n{summary_str}", total_cost, last_model
127
158
 
128
- # Aggregate results
129
- overall_success = all(r["success"] for r in all_results)
130
- result = {
131
- "success": overall_success,
132
- "results": all_results,
133
- "total_attempts": sum(r["attempts"] for r in all_results),
134
- }
135
- return result, total_cost, model_name
136
159
  except click.Abort:
137
160
  raise
138
- except Exception as exception:
139
- handle_error(exception, "fix", ctx.obj.get("quiet", False))
140
- ctx.exit(1)
161
+ except Exception as e:
162
+ handle_error(e)
163
+ return None
@@ -39,8 +39,9 @@ from ..core.utils import _run_setup_utility
39
39
  )
40
40
  @click.option(
41
41
  "--target-coverage",
42
+ type=float,
42
43
  default=None,
43
- help="Desired code coverage percentage. Default: 10.0 or .pddrc value.",
44
+ help="Desired code coverage percentage. Default: 90.0 or .pddrc value.",
44
45
  )
45
46
  @click.option(
46
47
  "--dry-run",
@@ -64,7 +65,7 @@ def sync(
64
65
  budget: Optional[float],
65
66
  skip_verify: bool,
66
67
  skip_tests: bool,
67
- target_coverage: float,
68
+ target_coverage: Optional[float],
68
69
  dry_run: bool,
69
70
  log: bool,
70
71
  ) -> Optional[Tuple[str, float, str]]:
pdd/commands/misc.py CHANGED
@@ -39,6 +39,12 @@ from ..core.errors import handle_error
39
39
  default=None,
40
40
  help="List of keys to exclude from curly bracket doubling.",
41
41
  )
42
+ @click.option(
43
+ "--pdd-tags",
44
+ is_flag=True,
45
+ default=False,
46
+ help="Inject PDD metadata tags (<pdd-reason>, <pdd-interface>, <pdd-dependency>) from architecture.json.",
47
+ )
42
48
  @click.pass_context
43
49
  # No @track_cost as preprocessing is local, but return dummy tuple for callback
44
50
  def preprocess(
@@ -49,6 +55,7 @@ def preprocess(
49
55
  recursive: bool,
50
56
  double: bool,
51
57
  exclude: Optional[Tuple[str, ...]],
58
+ pdd_tags: bool,
52
59
  ) -> Optional[Tuple[str, float, str]]:
53
60
  """Preprocess a prompt file to prepare it for LLM use."""
54
61
  try:
@@ -62,6 +69,7 @@ def preprocess(
62
69
  recursive=recursive,
63
70
  double=double,
64
71
  exclude=list(exclude) if exclude else [],
72
+ pdd_tags=pdd_tags,
65
73
  )
66
74
 
67
75
  # Handle the result from preprocess_main