pdd-cli 0.0.32__py3-none-any.whl → 0.0.33__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 CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.0.32"
1
+ __version__ = "0.0.33"
2
2
 
3
3
  # Strength parameter used for LLM extraction across the codebase
4
4
  # Used in postprocessing, XML tagging, code generation, and other extraction operations. The module should have a large context window and be affordable.
@@ -27,7 +27,7 @@ PDD_APP_NAME = "PDD Code Generator"
27
27
 
28
28
  # Cloud function URL
29
29
  CLOUD_GENERATE_URL = "https://us-central1-prompt-driven-development.cloudfunctions.net/generateCode"
30
- CLOUD_REQUEST_TIMEOUT = 200 # seconds
30
+ CLOUD_REQUEST_TIMEOUT = 400 # seconds
31
31
 
32
32
  console = Console()
33
33
 
@@ -59,8 +59,8 @@ def is_git_repository(path: Optional[str] = None) -> bool:
59
59
  return False
60
60
 
61
61
 
62
- def get_git_committed_content(file_path: str) -> Optional[str]:
63
- """Gets the content of the file as it was in the last commit (HEAD)."""
62
+ def get_git_content_at_ref(file_path: str, git_ref: str = "HEAD") -> Optional[str]:
63
+ """Gets the content of the file as it was at the specified git_ref."""
64
64
  abs_file_path = pathlib.Path(file_path).resolve()
65
65
  if not is_git_repository(str(abs_file_path.parent)):
66
66
  return None
@@ -77,13 +77,13 @@ def get_git_committed_content(file_path: str) -> Optional[str]:
77
77
  # console.print(f"[yellow]File {file_path} is not under git root {git_root}.[/yellow]")
78
78
  return None
79
79
 
80
- returncode, stdout, stderr = _run_git_command(["git", "show", f"HEAD:{relative_path.as_posix()}"], cwd=str(git_root))
80
+ returncode, stdout, stderr = _run_git_command(["git", "show", f"{git_ref}:{relative_path.as_posix()}"], cwd=str(git_root))
81
81
  if returncode == 0:
82
82
  return stdout
83
83
  else:
84
- # File might be new, or other git error. Not necessarily an error for this function's purpose.
85
- # if "does not exist" not in stderr and "exists on disk, but not in 'HEAD'" not in stderr and console.is_terminal:
86
- # console.print(f"[yellow]Git (show) warning for {file_path}: {stderr}[/yellow]")
84
+ # File might not exist at that ref, or other git error.
85
+ # if "does not exist" not in stderr and "exists on disk, but not in" not in stderr and console.is_terminal: # Be less noisy for common cases
86
+ # console.print(f"[yellow]Git (show) warning for {file_path} at {git_ref}: {stderr}[/yellow]")
87
87
  return None
88
88
 
89
89
  def get_file_git_status(file_path: str) -> str:
@@ -192,14 +192,98 @@ def code_generator_main(
192
192
  if verbose:
193
193
  console.print(f"Using specified original prompt: [cyan]{original_prompt_file_path}[/cyan]")
194
194
  elif is_git_repository(str(pathlib.Path(prompt_file).parent)):
195
- original_prompt_git_content = get_git_committed_content(prompt_file)
196
- if original_prompt_git_content is not None:
197
- original_prompt_content_for_incremental = original_prompt_git_content
198
- can_attempt_incremental = True
195
+ # prompt_content is the current on-disk version
196
+ head_prompt_content = get_git_content_at_ref(prompt_file, git_ref="HEAD")
197
+
198
+ if head_prompt_content is not None:
199
+ # Compare on-disk content (prompt_content) with HEAD content
200
+ if prompt_content.strip() != head_prompt_content.strip():
201
+ # Uncommitted changes exist. Original is HEAD, new is on-disk.
202
+ original_prompt_content_for_incremental = head_prompt_content
203
+ can_attempt_incremental = True
204
+ if verbose:
205
+ console.print(f"On-disk [cyan]{prompt_file}[/cyan] has uncommitted changes. Using HEAD version as original prompt.")
206
+ else:
207
+ # On-disk is identical to HEAD. Search for a prior *different* version.
208
+ if verbose:
209
+ console.print(f"On-disk [cyan]{prompt_file}[/cyan] matches HEAD. Searching for a prior *different* version as original prompt.")
210
+
211
+ new_prompt_candidate = head_prompt_content # This is also prompt_content (on-disk)
212
+ found_different_prior = False
213
+
214
+ git_root_path_obj: Optional[pathlib.Path] = None
215
+ prompt_file_rel_to_root_str: Optional[str] = None
216
+
217
+ try:
218
+ abs_prompt_file_path = pathlib.Path(prompt_file).resolve()
219
+ temp_git_root_rc, temp_git_root_str, temp_git_root_stderr = _run_git_command(
220
+ ["git", "rev-parse", "--show-toplevel"],
221
+ cwd=str(abs_prompt_file_path.parent)
222
+ )
223
+ if temp_git_root_rc == 0:
224
+ git_root_path_obj = pathlib.Path(temp_git_root_str)
225
+ prompt_file_rel_to_root_str = abs_prompt_file_path.relative_to(git_root_path_obj).as_posix()
226
+ elif verbose:
227
+ console.print(f"[yellow]Git (rev-parse) failed for {prompt_file}: {temp_git_root_stderr}. Cannot search history for prior different version.[/yellow]")
228
+
229
+ except ValueError: # If file is not under git root
230
+ if verbose:
231
+ console.print(f"[yellow]File {prompt_file} not under a detected git root. Cannot search history.[/yellow]")
232
+ except Exception as e_git_setup:
233
+ if verbose:
234
+ console.print(f"[yellow]Error setting up git info for {prompt_file}: {e_git_setup}. Cannot search history.[/yellow]")
235
+
236
+ if git_root_path_obj and prompt_file_rel_to_root_str:
237
+ MAX_COMMITS_TO_SEARCH = 10 # How far back to look
238
+ log_cmd = ["git", "log", f"--pretty=format:%H", f"-n{MAX_COMMITS_TO_SEARCH}", "--", prompt_file_rel_to_root_str]
239
+
240
+ log_rc, log_stdout, log_stderr = _run_git_command(log_cmd, cwd=str(git_root_path_obj))
241
+
242
+ if log_rc == 0 and log_stdout.strip():
243
+ shas = log_stdout.strip().split('\\n')
244
+ if verbose:
245
+ console.print(f"Found {len(shas)} commits for [cyan]{prompt_file_rel_to_root_str}[/cyan] in recent history (up to {MAX_COMMITS_TO_SEARCH}).")
246
+
247
+ if len(shas) > 1: # Need at least one commit before the one matching head_prompt_content
248
+ for prior_sha in shas[1:]: # Iterate starting from the commit *before* HEAD's version of the file
249
+ if verbose:
250
+ console.print(f" Checking commit {prior_sha[:7]} for content of [cyan]{prompt_file}[/cyan]...")
251
+
252
+ # get_git_content_at_ref uses the original prompt_file path,
253
+ # which it resolves internally relative to the git root.
254
+ prior_content = get_git_content_at_ref(prompt_file, prior_sha)
255
+
256
+ if prior_content is not None:
257
+ if prior_content.strip() != new_prompt_candidate.strip():
258
+ original_prompt_content_for_incremental = prior_content
259
+ can_attempt_incremental = True
260
+ found_different_prior = True
261
+ if verbose:
262
+ console.print(f" [green]Found prior different version at commit {prior_sha[:7]}. Using as original prompt.[/green]")
263
+ break
264
+ elif verbose:
265
+ console.print(f" Content at {prior_sha[:7]} is identical to current HEAD. Skipping.")
266
+ elif verbose:
267
+ console.print(f" Could not retrieve content for [cyan]{prompt_file}[/cyan] at commit {prior_sha[:7]}.")
268
+ else:
269
+ if verbose:
270
+ console.print(f" File [cyan]{prompt_file_rel_to_root_str}[/cyan] has less than 2 versions in recent history at this path.")
271
+ elif verbose:
272
+ console.print(f"[yellow]Git (log) failed for {prompt_file_rel_to_root_str} or no history found: {log_stderr}[/yellow]")
273
+
274
+ if not found_different_prior:
275
+ original_prompt_content_for_incremental = new_prompt_candidate
276
+ can_attempt_incremental = True
277
+ if verbose:
278
+ console.print(
279
+ f"[yellow]Warning: Could not find a prior *different* version of {prompt_file} "
280
+ f"within the last {MAX_COMMITS_TO_SEARCH if git_root_path_obj else 'N/A'} relevant commits. "
281
+ f"Using current HEAD version as original (prompts will be identical).[/yellow]"
282
+ )
283
+ else:
284
+ # File not in HEAD, cannot determine git-based original prompt.
199
285
  if verbose:
200
- console.print(f"Using last committed version of [cyan]{prompt_file}[/cyan] as original prompt.")
201
- elif verbose:
202
- console.print(f"[yellow]Warning: Could not find committed version of {prompt_file} in git for incremental generation.[/yellow]")
286
+ console.print(f"[yellow]Warning: Could not find committed version of {prompt_file} in git (HEAD) for incremental generation.[/yellow]")
203
287
 
204
288
  if force_incremental_flag and existing_code_content:
205
289
  if not (original_prompt_content_for_incremental or "original_prompt_file" in input_strings): # Check if original prompt is actually available
pdd/context_generator.py CHANGED
@@ -33,11 +33,6 @@ def context_generator(code_module: str, prompt: str, language: str = "python", s
33
33
  print("[red]Error: prompt is missing.[/red]")
34
34
  return None, 0.0, None
35
35
 
36
- supported_languages = ["python", "javascript", "java"]
37
- if language not in supported_languages:
38
- if verbose:
39
- print(f"[red]Error: Unsupported language '{language}'.[/red]")
40
- return None, 0.0, None
41
36
 
42
37
  if not (0 <= strength <= 1):
43
38
  if verbose:
@@ -25,7 +25,7 @@ def context_generator_main(ctx: click.Context, prompt_file: str, code_file: str,
25
25
  command_options = {
26
26
  "output": output
27
27
  }
28
- input_strings, output_file_paths, _ = construct_paths(
28
+ input_strings, output_file_paths, language = construct_paths(
29
29
  input_file_paths=input_file_paths,
30
30
  force=ctx.obj.get('force', False),
31
31
  quiet=ctx.obj.get('quiet', False),
@@ -41,6 +41,7 @@ def context_generator_main(ctx: click.Context, prompt_file: str, code_file: str,
41
41
  strength = ctx.obj.get('strength', 0.5)
42
42
  temperature = ctx.obj.get('temperature', 0)
43
43
  example_code, total_cost, model_name = context_generator(
44
+ language=language,
44
45
  code_module=code_content,
45
46
  prompt=prompt_content,
46
47
  strength=strength,
@@ -12,6 +12,7 @@ Go,//,.go
12
12
  Rust,//,.rs
13
13
  Kotlin,//,.kt
14
14
  TypeScript,//,.ts
15
+ TypeScriptReact,//,.tsx
15
16
  C#,//,.cs
16
17
  SQL,--,.sql
17
18
  Shell,#,.sh
pdd/postprocess.py CHANGED
@@ -3,6 +3,7 @@ from rich import print
3
3
  from pydantic import BaseModel, Field
4
4
  from .load_prompt_template import load_prompt_template
5
5
  from .llm_invoke import llm_invoke
6
+ from . import DEFAULT_TIME
6
7
 
7
8
  class ExtractedCode(BaseModel):
8
9
  """Pydantic model for the extracted code."""
@@ -18,12 +19,13 @@ def postprocess_0(text: str) -> str:
18
19
  in_code_block = False
19
20
 
20
21
  for line in lines:
21
- if line.startswith('```'):
22
+ if '```' in line: # MODIFIED: Was line.startswith('```')
22
23
  if not in_code_block:
23
- # Skip the language identifier line
24
+ # Skip the language identifier line / content on opening delimiter line
24
25
  in_code_block = True
25
26
  continue
26
27
  else:
28
+ # Content on closing delimiter line is skipped
27
29
  in_code_block = False
28
30
  continue
29
31
  if in_code_block:
@@ -36,6 +38,7 @@ def postprocess(
36
38
  language: str,
37
39
  strength: float = 0.9,
38
40
  temperature: float = 0,
41
+ time: float = DEFAULT_TIME,
39
42
  verbose: bool = False
40
43
  ) -> Tuple[str, float, str]:
41
44
  """
@@ -46,6 +49,7 @@ def postprocess(
46
49
  language (str): The programming language of the code to extract
47
50
  strength (float): The strength of the LLM model to use (0-1)
48
51
  temperature (float): The temperature parameter for the LLM (0-1)
52
+ time (float): The thinking effort for the LLM model (0-1)
49
53
  verbose (bool): Whether to print detailed processing information
50
54
 
51
55
  Returns:
@@ -87,6 +91,7 @@ def postprocess(
87
91
  input_json=input_json,
88
92
  strength=strength,
89
93
  temperature=temperature,
94
+ time=time,
90
95
  verbose=verbose,
91
96
  output_pydantic=ExtractedCode
92
97
  )
@@ -94,14 +99,14 @@ def postprocess(
94
99
  if not response or 'result' not in response:
95
100
  raise ValueError("Failed to get valid response from LLM")
96
101
 
97
- extracted_code: ExtractedCode = response['result']
98
- code_text = extracted_code.extracted_code
102
+ extracted_code_obj: ExtractedCode = response['result'] # Renamed for clarity
103
+ code_text = extracted_code_obj.extracted_code
99
104
 
100
105
  # Step 3c: Remove triple backticks and language identifier if present
101
106
  lines = code_text.split('\n')
102
107
  if lines and lines[0].startswith('```'):
103
108
  lines = lines[1:]
104
- if lines and lines[-1].startswith('```'):
109
+ if lines and lines[-1].startswith('```'): # Check if lines is not empty again after potentially removing first line
105
110
  lines = lines[:-1]
106
111
 
107
112
  final_code = '\n'.join(lines)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdd-cli
3
- Version: 0.0.32
3
+ Version: 0.0.33
4
4
  Summary: PDD (Prompt-Driven Development) Command Line Interface
5
5
  Author: Greg Tanaka
6
6
  Author-email: glt@alumni.caltech.edu
@@ -46,7 +46,7 @@ Requires-Dist: pytest-asyncio; extra == "dev"
46
46
  Requires-Dist: z3-solver; extra == "dev"
47
47
  Dynamic: license-file
48
48
 
49
- .. image:: https://img.shields.io/badge/pdd--cli-v0.0.32-blue
49
+ .. image:: https://img.shields.io/badge/pdd--cli-v0.0.33-blue
50
50
  :alt: PDD-CLI Version
51
51
 
52
52
  PDD (Prompt-Driven Development) Command Line Interface
@@ -130,7 +130,7 @@ After installation, verify:
130
130
 
131
131
  pdd --version
132
132
 
133
- You'll see the current PDD version (e.g., 0.0.32).
133
+ You'll see the current PDD version (e.g., 0.0.33).
134
134
 
135
135
  Advanced Installation Tips
136
136
  --------------------------
@@ -1,4 +1,4 @@
1
- pdd/__init__.py,sha256=oBlK2EdKLxWULcsuHgrlD34jImz8M12FUeCXxTkbxIk,632
1
+ pdd/__init__.py,sha256=Dz0E3y_UahIvzJmwRPuYlso-fufI57LqGEq8bmJDJEE,632
2
2
  pdd/auto_deps_main.py,sha256=NVLqL5FHxe2eorViXTuh8z2zH9Sb-b6MNN9aZ1hqevY,3552
3
3
  pdd/auto_include.py,sha256=aCa2QXDlOdKbh4vS3uDjWptkHB_Qv3QBNCbZe6mGWoo,6074
4
4
  pdd/auto_update.py,sha256=Pfav1hrqQIDjZIPuIvryBeM7k-Rc72feVUTJZPtigaU,2889
@@ -9,13 +9,13 @@ pdd/change_main.py,sha256=Tk0aHY8Z2d-d0m7lLfc_HqgOqs4x_dJD1IrVZSxuxIM,25580
9
9
  pdd/cli.py,sha256=VFoyx3iJmFeHCc4HhOc_7tiz3FY9oJjCUtS9PR1wwl0,38341
10
10
  pdd/cmd_test_main.py,sha256=aSCxRnSurg15AvPcJDAPp9xy8p_qqnjU1oV14Hi2R54,5301
11
11
  pdd/code_generator.py,sha256=DqQNN6jCNjSJvHi0IFyqkSfak6LeDG-yQHPYnvd4AJQ,4424
12
- pdd/code_generator_main.py,sha256=wup3O2dVh9JzlGsWtXvypqAHgHyBZHOWAe3NJuV_-g4,18648
12
+ pdd/code_generator_main.py,sha256=oCI35RqQ7gBov8mncVg1mhdDNX-0jTsoIeSzrz7WpAk,25109
13
13
  pdd/comment_line.py,sha256=sX2hf4bG1fILi_rvI9MkkwCZ2IitgKkW7nOiw8aQKPY,1845
14
14
  pdd/conflicts_in_prompts.py,sha256=XaEm9jIMcbENTyhphD8NXs2EmRxuPu1EI8GHrsiRwq0,4687
15
15
  pdd/conflicts_main.py,sha256=O87s9baSa9DJMndxPIdsnYO_spoajcv9jii3XYt_-fM,3473
16
16
  pdd/construct_paths.py,sha256=AE3vblj2v21ZdReM40pz47gvmXg-RZjuR_2FALj_9fs,17672
17
- pdd/context_generator.py,sha256=MO483MqtMR5EUanllD7Ru5U9idcVMIMutntcWMn31cI,5847
18
- pdd/context_generator_main.py,sha256=TtsY3jHictdEjmB4cHyNwXmZW_LfHJp3KW3UXyzR2cU,2735
17
+ pdd/context_generator.py,sha256=KQAaJRwVpsPOF4y5lhP3DpIrlxhR39C0hNyTAi1Kx2U,5618
18
+ pdd/context_generator_main.py,sha256=WSS7uRkS2wi8HCixDA3_xzFuPqFRF_X2tGe6K3loUZc,2773
19
19
  pdd/continue_generation.py,sha256=upZw77fKqHZ5IS8Ful7eioTi9VTqeuY1V9vzIwHeOJQ,5419
20
20
  pdd/crash_main.py,sha256=yveWWJWxCOzRLxPk1m1rgm4tNwpAk5jYRvYyItAaU2w,7262
21
21
  pdd/detect_change.py,sha256=t70NAgakVc2u7XiI-lZjuR2RZ8Mrd3lJwRPu8I8s_P4,5310
@@ -47,7 +47,7 @@ pdd/mcp_config.json,sha256=D3ctWHlShvltbtH37zbYb6smVE0V80_lGjDKDIqsSBE,124
47
47
  pdd/pdd_completion.fish,sha256=rs-43fa3kcDBN1uy4oxiofLAWmaqW0U2j5Mu4wCHh5M,6121
48
48
  pdd/pdd_completion.sh,sha256=qurWrEksqptjryBZszxHv6i0MqgnIqJenMBDrzMgI98,4535
49
49
  pdd/pdd_completion.zsh,sha256=-yz69Rs4lnJ-bRAF8H2Tzk0GuDUo-BWjytE3fv5wTS8,13458
50
- pdd/postprocess.py,sha256=7Dt4C7hZZbqCpYK0LG2Ui_vIUYw9UTN3w5Wgd_JZYBs,4021
50
+ pdd/postprocess.py,sha256=jWJSUPP7bDChyTEek35UOdy6fhU6c5EoDSoMypGwIdE,4402
51
51
  pdd/postprocess_0.py,sha256=OW17GyCFLYErCyWh2tL4syuho3q2yFf2wyekQ4BLdPM,2168
52
52
  pdd/preprocess.py,sha256=UB1rqSNscUC-JHujvGb11LJ5OadZ3GVD1Qeq1dI6HMc,9508
53
53
  pdd/preprocess_main.py,sha256=dAgFGmjuJB1taZl31c1sY2jMGtQgjnWLbpeB7EFtojY,2977
@@ -64,7 +64,7 @@ pdd/update_main.py,sha256=5a4nsOOaAXULdk0BS9pj4blZ_QHBFeET37uaAqoJI2g,3912
64
64
  pdd/update_model_costs.py,sha256=zfGqWoVIjBppKUt1Naq2ZsIdiucwfH6at2DflcwkJf8,22998
65
65
  pdd/update_prompt.py,sha256=OdPRIAMu7OBx7E4SOU95hWgdtBY4oO8XOe1dvPChMlU,4351
66
66
  pdd/xml_tagger.py,sha256=5AWzOboNuXMJmmIpi1hhPPAB6nxbBOkRqgoPLpoGYT8,4292
67
- pdd/data/language_format.csv,sha256=xUTmFHXSBVBRfPV-NKG3oWo5_ped5ukP-ekFcIlVzJk,877
67
+ pdd/data/language_format.csv,sha256=X7jj_clC6dA93ij0TUPNd9oJ2tHyKUKXlWo1XVhP6zo,901
68
68
  pdd/data/llm_model.csv,sha256=BZioMyxUlDuJdcxFCDV2BTw1ssiHKZBf4OxELIy4JGY,1487
69
69
  pdd/prompts/auto_include_LLM.prompt,sha256=0t-Jmm5o6vVTmqsISTUiewqPT8bB389UZnJoHZvgtu4,13967
70
70
  pdd/prompts/bug_to_unit_test_LLM.prompt,sha256=KdMkvRVnjVSf0NTYIaDXIMT93xPttXEwkMpjWx5leLs,1588
@@ -101,9 +101,9 @@ pdd/prompts/trim_results_start_LLM.prompt,sha256=OKz8fAf1cYWKWgslFOHEkUpfaUDARh3
101
101
  pdd/prompts/unfinished_prompt_LLM.prompt,sha256=-JgBpiPTQZdWOAwOG1XpfpD9waynFTAT3Jo84eQ4bTw,1543
102
102
  pdd/prompts/update_prompt_LLM.prompt,sha256=prIc8uLp2jqnLTHt6JvWDZGanPZipivhhYeXe0lVaYw,1328
103
103
  pdd/prompts/xml_convertor_LLM.prompt,sha256=YGRGXJeg6EhM9690f-SKqQrKqSJjLFD51UrPOlO0Frg,2786
104
- pdd_cli-0.0.32.dist-info/licenses/LICENSE,sha256=-1bjYH-CEjGEQ8VixtnRYuu37kN6F9NxmZSDkBuUQ9o,1062
105
- pdd_cli-0.0.32.dist-info/METADATA,sha256=gnrubUf69rPVr3t01FvagrPuxrJ3B6JRbHXjYQYB3OQ,7778
106
- pdd_cli-0.0.32.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
107
- pdd_cli-0.0.32.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
108
- pdd_cli-0.0.32.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
109
- pdd_cli-0.0.32.dist-info/RECORD,,
104
+ pdd_cli-0.0.33.dist-info/licenses/LICENSE,sha256=-1bjYH-CEjGEQ8VixtnRYuu37kN6F9NxmZSDkBuUQ9o,1062
105
+ pdd_cli-0.0.33.dist-info/METADATA,sha256=3YpnYiyxVO4po25BTjUXzs-ara96spnI4RSnoOMx3X0,7778
106
+ pdd_cli-0.0.33.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
107
+ pdd_cli-0.0.33.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
108
+ pdd_cli-0.0.33.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
109
+ pdd_cli-0.0.33.dist-info/RECORD,,