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/context_generator.py
CHANGED
|
@@ -5,6 +5,7 @@ from .llm_invoke import llm_invoke
|
|
|
5
5
|
from .unfinished_prompt import unfinished_prompt
|
|
6
6
|
from .continue_generation import continue_generation
|
|
7
7
|
from .postprocess import postprocess
|
|
8
|
+
from . import EXTRACTION_STRENGTH
|
|
8
9
|
|
|
9
10
|
def context_generator(code_module: str, prompt: str, language: str = "python", strength: float = 0.5, temperature: float = 0, verbose: bool = False) -> tuple:
|
|
10
11
|
"""
|
|
@@ -115,7 +116,7 @@ def context_generator(code_module: str, prompt: str, language: str = "python", s
|
|
|
115
116
|
example_code, postprocess_cost, postprocess_model = postprocess(
|
|
116
117
|
llm_output=final_llm_output,
|
|
117
118
|
language=language,
|
|
118
|
-
strength=
|
|
119
|
+
strength=EXTRACTION_STRENGTH,
|
|
119
120
|
temperature=temperature,
|
|
120
121
|
verbose=verbose
|
|
121
122
|
)
|
pdd/continue_generation.py
CHANGED
|
@@ -6,13 +6,16 @@ from .load_prompt_template import load_prompt_template
|
|
|
6
6
|
from .preprocess import preprocess
|
|
7
7
|
from .llm_invoke import llm_invoke
|
|
8
8
|
from .unfinished_prompt import unfinished_prompt
|
|
9
|
+
from . import EXTRACTION_STRENGTH
|
|
9
10
|
|
|
10
11
|
console = Console()
|
|
11
12
|
|
|
12
13
|
class TrimResultsStartOutput(BaseModel):
|
|
14
|
+
explanation: str = Field(description="The explanation of how you determined what to cut out")
|
|
13
15
|
code_block: str = Field(description="The trimmed code block from the start")
|
|
14
16
|
|
|
15
17
|
class TrimResultsOutput(BaseModel):
|
|
18
|
+
explanation: str = Field(description="The explanation of the code block")
|
|
16
19
|
trimmed_continued_generation: str = Field(description="The trimmed continuation of the generation")
|
|
17
20
|
|
|
18
21
|
def continue_generation(
|
|
@@ -69,7 +72,7 @@ def continue_generation(
|
|
|
69
72
|
trim_start_response = llm_invoke(
|
|
70
73
|
prompt=processed_prompts['trim_start'],
|
|
71
74
|
input_json={"LLM_OUTPUT": llm_output},
|
|
72
|
-
strength=0.
|
|
75
|
+
strength=0.75,
|
|
73
76
|
temperature=0,
|
|
74
77
|
output_pydantic=TrimResultsStartOutput,
|
|
75
78
|
verbose=verbose
|
|
@@ -119,7 +122,7 @@ def continue_generation(
|
|
|
119
122
|
"CONTINUED_GENERATION": continue_result,
|
|
120
123
|
"GENERATED_RESULTS": code_block[-200:]
|
|
121
124
|
},
|
|
122
|
-
strength=
|
|
125
|
+
strength=EXTRACTION_STRENGTH,
|
|
123
126
|
temperature=0,
|
|
124
127
|
output_pydantic=TrimResultsOutput,
|
|
125
128
|
verbose=verbose
|
pdd/crash_main.py
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import sys
|
|
2
|
-
from typing import Tuple, Optional
|
|
2
|
+
from typing import Tuple, Optional, Dict, Any
|
|
3
3
|
import click
|
|
4
4
|
from rich import print as rprint
|
|
5
|
+
from . import DEFAULT_STRENGTH
|
|
6
|
+
from pathlib import Path
|
|
5
7
|
|
|
6
8
|
from .construct_paths import construct_paths
|
|
7
9
|
from .fix_code_loop import fix_code_loop
|
|
10
|
+
# Import fix_code_module_errors conditionally or ensure it's always available
|
|
11
|
+
try:
|
|
12
|
+
from .fix_code_module_errors import fix_code_module_errors
|
|
13
|
+
except ImportError:
|
|
14
|
+
# Handle case where fix_code_module_errors might not be available if not needed
|
|
15
|
+
fix_code_module_errors = None
|
|
8
16
|
|
|
9
17
|
def crash_main(
|
|
10
18
|
ctx: click.Context,
|
|
@@ -39,6 +47,13 @@ def crash_main(
|
|
|
39
47
|
- float: Total cost of all fix attempts
|
|
40
48
|
- str: The name of the model used
|
|
41
49
|
"""
|
|
50
|
+
# Ensure ctx.obj and ctx.params exist and are dictionaries
|
|
51
|
+
ctx.obj = ctx.obj if isinstance(ctx.obj, dict) else {}
|
|
52
|
+
ctx.params = ctx.params if isinstance(ctx.params, dict) else {}
|
|
53
|
+
|
|
54
|
+
quiet = ctx.params.get("quiet", ctx.obj.get("quiet", False))
|
|
55
|
+
verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False)) # Get verbose flag
|
|
56
|
+
|
|
42
57
|
try:
|
|
43
58
|
# Construct file paths
|
|
44
59
|
input_file_paths = {
|
|
@@ -47,13 +62,13 @@ def crash_main(
|
|
|
47
62
|
"program_file": program_file,
|
|
48
63
|
"error_file": error_file
|
|
49
64
|
}
|
|
50
|
-
command_options = {
|
|
65
|
+
command_options: Dict[str, Any] = {
|
|
51
66
|
"output": output,
|
|
52
67
|
"output_program": output_program
|
|
53
68
|
}
|
|
54
69
|
|
|
55
70
|
force = ctx.params.get("force", ctx.obj.get("force", False))
|
|
56
|
-
quiet = ctx.params.get("quiet", ctx.obj.get("quiet", False))
|
|
71
|
+
# quiet = ctx.params.get("quiet", ctx.obj.get("quiet", False)) # Already defined above
|
|
57
72
|
|
|
58
73
|
input_strings, output_file_paths, _ = construct_paths(
|
|
59
74
|
input_file_paths=input_file_paths,
|
|
@@ -70,46 +85,58 @@ def crash_main(
|
|
|
70
85
|
error_content = input_strings["error_file"]
|
|
71
86
|
|
|
72
87
|
# Get model parameters from context
|
|
73
|
-
strength = ctx.obj.get("strength",
|
|
88
|
+
strength = ctx.obj.get("strength", DEFAULT_STRENGTH)
|
|
74
89
|
temperature = ctx.obj.get("temperature", 0)
|
|
75
90
|
|
|
76
|
-
verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False))
|
|
91
|
+
# verbose = ctx.params.get("verbose", ctx.obj.get("verbose", False)) # Already defined above
|
|
77
92
|
|
|
78
93
|
if loop:
|
|
79
94
|
# Use iterative fixing process
|
|
80
|
-
success,
|
|
95
|
+
success, final_program, final_code, attempts, cost, model = fix_code_loop(
|
|
81
96
|
code_file, prompt_content, program_file, strength, temperature, max_attempts or 3, budget or 5.0, error_file, verbose
|
|
82
97
|
)
|
|
83
98
|
else:
|
|
84
99
|
# Use single fix attempt
|
|
85
|
-
|
|
86
|
-
|
|
100
|
+
if fix_code_module_errors is None:
|
|
101
|
+
raise ImportError("fix_code_module_errors is required but not available.")
|
|
102
|
+
# Note: fix_code_module_errors returns 7 values according to example
|
|
103
|
+
# update_program, update_code, fixed_program, fixed_code, program_code_fix, cost, model
|
|
104
|
+
# The current code unpacks 7 values, which matches the example.
|
|
105
|
+
update_program, update_code, final_program, final_code, program_code_fix, cost, model = fix_code_module_errors(
|
|
87
106
|
program_content, prompt_content, code_content, error_content, strength, temperature, verbose
|
|
88
107
|
)
|
|
89
|
-
success = True
|
|
108
|
+
success = True # Assume success after one attempt if no exception
|
|
90
109
|
attempts = 1
|
|
91
110
|
|
|
92
111
|
# Ensure we have content to write, falling back to original content if needed
|
|
93
|
-
if final_code == "":
|
|
94
|
-
final_code = code_content
|
|
95
|
-
|
|
96
112
|
if final_program == "":
|
|
97
113
|
final_program = program_content
|
|
98
114
|
|
|
115
|
+
if final_code == "":
|
|
116
|
+
final_code = code_content
|
|
117
|
+
|
|
99
118
|
# Determine whether to write the files based on whether paths are provided
|
|
100
|
-
|
|
101
|
-
|
|
119
|
+
output_code_path_str = output_file_paths.get("output")
|
|
120
|
+
output_program_path_str = output_file_paths.get("output_program")
|
|
121
|
+
|
|
122
|
+
should_write_code = output_code_path_str is not None
|
|
123
|
+
should_write_program = output_program_path_str is not None
|
|
102
124
|
|
|
103
125
|
# Write output files
|
|
104
126
|
if should_write_code:
|
|
105
|
-
|
|
127
|
+
output_code_path = Path(output_code_path_str)
|
|
128
|
+
output_code_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
|
|
129
|
+
with open(output_code_path, "w") as f:
|
|
106
130
|
f.write(final_code)
|
|
107
131
|
|
|
108
132
|
if should_write_program:
|
|
109
|
-
|
|
133
|
+
output_program_path = Path(output_program_path_str)
|
|
134
|
+
output_program_path.parent.mkdir(parents=True, exist_ok=True) # Ensure directory exists
|
|
135
|
+
with open(output_program_path, "w") as f:
|
|
110
136
|
f.write(final_program)
|
|
111
137
|
|
|
112
|
-
# Provide user feedback
|
|
138
|
+
# Provide user feedback (using quiet flag as per current implementation)
|
|
139
|
+
# To strictly follow the prompt's last note, change 'if not quiet:' to 'if verbose:'
|
|
113
140
|
if not quiet:
|
|
114
141
|
if success:
|
|
115
142
|
rprint("[bold green]Crash fix completed successfully.[/bold green]")
|
|
@@ -119,13 +146,21 @@ def crash_main(
|
|
|
119
146
|
rprint(f"[bold]Total attempts:[/bold] {attempts}")
|
|
120
147
|
rprint(f"[bold]Total cost:[/bold] ${cost:.2f}")
|
|
121
148
|
if should_write_code:
|
|
122
|
-
rprint(f"[bold]Fixed code saved to:[/bold] {
|
|
149
|
+
rprint(f"[bold]Fixed code saved to:[/bold] {output_code_path_str}")
|
|
123
150
|
if should_write_program:
|
|
124
|
-
rprint(f"[bold]Fixed program saved to:[/bold] {
|
|
151
|
+
rprint(f"[bold]Fixed program saved to:[/bold] {output_program_path_str}")
|
|
125
152
|
|
|
126
153
|
return success, final_code, final_program, attempts, cost, model
|
|
127
154
|
|
|
155
|
+
except FileNotFoundError as e:
|
|
156
|
+
if not quiet:
|
|
157
|
+
# Provide a more specific error message for file not found
|
|
158
|
+
rprint(f"[bold red]Error:[/bold red] Input file not found: {e}")
|
|
159
|
+
sys.exit(1)
|
|
128
160
|
except Exception as e:
|
|
129
161
|
if not quiet:
|
|
130
|
-
rprint(f"[bold red]
|
|
162
|
+
rprint(f"[bold red]An unexpected error occurred:[/bold red] {str(e)}")
|
|
163
|
+
# Consider logging the full traceback here for debugging
|
|
164
|
+
# import traceback
|
|
165
|
+
# traceback.print_exc()
|
|
131
166
|
sys.exit(1)
|
pdd/data/llm_model.csv
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
provider,model,input,output,coding_arena_elo,base_url,api_key,
|
|
2
|
-
OpenAI,
|
|
3
|
-
|
|
4
|
-
Anthropic,
|
|
5
|
-
OpenAI,
|
|
6
|
-
Google,
|
|
7
|
-
|
|
8
|
-
Anthropic,claude-3-7-sonnet-20250219,3,15,
|
|
9
|
-
Google,gemini-2.5-pro-
|
|
10
|
-
OpenAI,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
OpenAI,
|
|
14
|
-
|
|
15
|
-
OpenAI,
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
provider,model,input,output,coding_arena_elo,base_url,api_key,max_reasoning_tokens,structured_output,reasoning_type
|
|
2
|
+
OpenAI,gpt-4.1-nano,0.1,0.4,1249,,OPENAI_API_KEY,0,True,none
|
|
3
|
+
xai,xai/grok-3-beta,3.0,15.0,1332,https://api.x.ai/v1,XAI_API_KEY,0,False,none
|
|
4
|
+
Anthropic,claude-3-5-haiku-20241022,.8,4,1261,,ANTHROPIC_API_KEY,0,True,none
|
|
5
|
+
OpenAI,deepseek/deepseek-chat,.27,1.1,1353,https://api.deepseek.com/beta,DEEPSEEK_API_KEY,0,False,none
|
|
6
|
+
Google,vertex_ai/gemini-2.5-flash-preview-04-17,0.15,0.6,1330,,VERTEX_CREDENTIALS,0,True,effort
|
|
7
|
+
Google,gemini-2.5-pro-exp-03-25,1.25,10.0,1360,,GOOGLE_API_KEY,0,True,none
|
|
8
|
+
Anthropic,claude-3-7-sonnet-20250219,3.0,15.0,1340,,ANTHROPIC_API_KEY,64000,True,budget
|
|
9
|
+
Google,vertex_ai/gemini-2.5-pro-preview-05-06,1.25,10.0,1361,,VERTEX_CREDENTIALS,0,True,none
|
|
10
|
+
OpenAI,o4-mini,1.1,4.4,1333,,OPENAI_API_KEY,0,True,effort
|
|
11
|
+
OpenAI,o3,10.0,40.0,1389,,OPENAI_API_KEY,0,True,effort
|
|
12
|
+
OpenAI,gpt-4.1,2.0,8.0,1335,,OPENAI_API_KEY,0,True,none
|
|
13
|
+
OpenAI,deepseek/deepseek-reasoner,0.55,2.19,1337,https://api.deepseek.com/beta,DEEPSEEK_API_KEY,0,False,none
|
|
14
|
+
Fireworks,fireworks_ai/accounts/fireworks/models/deepseek-r1,3.0,8.0,1338,,FIREWORKS_API_KEY,0,False,none
|
|
15
|
+
OpenAI,chatgpt-4o-latest,5,15,1369,,OPENAI_API_KEY,0,False,none
|
|
16
|
+
Anthropic,bedrock/us.anthropic.claude-3-7-sonnet-20250219-v1:0,3.0,15.0,1339,,,64000,True,budget
|
|
17
|
+
OpenAI,azure/o4-mini,1.1,4.4,1334,,OPENAI_API_KEY,0,True,effort
|
|
18
|
+
OpenAI,openai/mlx-community/Qwen3-30B-A3B-4bit,0,0,1293,http://localhost:8080,,0,False,none
|
pdd/detect_change.py
CHANGED
|
@@ -3,6 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
from rich.console import Console
|
|
4
4
|
from rich.markdown import Markdown
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
|
+
from . import EXTRACTION_STRENGTH
|
|
6
7
|
|
|
7
8
|
from .preprocess import preprocess
|
|
8
9
|
from .load_prompt_template import load_prompt_template
|
|
@@ -101,7 +102,7 @@ def detect_change(
|
|
|
101
102
|
extract_response = llm_invoke(
|
|
102
103
|
prompt=extract_prompt,
|
|
103
104
|
input_json={"llm_output": detect_response['result']},
|
|
104
|
-
strength=
|
|
105
|
+
strength=EXTRACTION_STRENGTH,
|
|
105
106
|
temperature=0.0,
|
|
106
107
|
verbose=verbose,
|
|
107
108
|
output_pydantic=ChangesList
|