pdd-cli 0.0.48__py3-none-any.whl → 0.0.49__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,6 +1,6 @@
1
1
  """PDD - Prompt Driven Development"""
2
2
 
3
- __version__ = "0.0.48"
3
+ __version__ = "0.0.49"
4
4
 
5
5
  # Strength parameter used for LLM extraction across the codebase
6
6
  # Used in postprocessing, XML tagging, code generation, and other extraction
pdd/llm_invoke.py CHANGED
@@ -6,7 +6,7 @@ import pandas as pd
6
6
  import litellm
7
7
  import logging # ADDED FOR DETAILED LOGGING
8
8
  import importlib.resources
9
- from litellm.caching.caching import Cache # Fix for LiteLLM v1.49.3+
9
+ from litellm.caching.caching import Cache # Fix for LiteLLM v1.75.5+
10
10
 
11
11
  # --- Configure Standard Python Logging ---
12
12
  logger = logging.getLogger("pdd.llm_invoke")
@@ -280,16 +280,22 @@ if GCS_BUCKET_NAME and GCS_HMAC_ACCESS_KEY_ID and GCS_HMAC_SECRET_ACCESS_KEY:
280
280
  elif 'AWS_REGION_NAME' in os.environ:
281
281
  pass # Or just leave it if the temporary setting wasn't done/needed
282
282
 
283
+ # Check if caching is disabled via environment variable
284
+ if os.getenv("LITELLM_CACHE_DISABLE") == "1":
285
+ logger.info("LiteLLM caching disabled via LITELLM_CACHE_DISABLE=1")
286
+ litellm.cache = None
287
+ cache_configured = True
288
+
283
289
  if not cache_configured:
284
290
  try:
285
- # Try SQLite-based cache as a fallback
291
+ # Try disk-based cache as a fallback
286
292
  sqlite_cache_path = PROJECT_ROOT / "litellm_cache.sqlite"
287
- configured_cache = Cache(type="sqlite", cache_path=str(sqlite_cache_path))
293
+ configured_cache = Cache(type="disk", disk_cache_dir=str(sqlite_cache_path))
288
294
  litellm.cache = configured_cache
289
- logger.info(f"LiteLLM SQLite cache configured at {sqlite_cache_path}")
295
+ logger.info(f"LiteLLM disk cache configured at {sqlite_cache_path}")
290
296
  cache_configured = True
291
297
  except Exception as e2:
292
- warnings.warn(f"Failed to configure LiteLLM SQLite cache: {e2}. Caching is disabled.")
298
+ warnings.warn(f"Failed to configure LiteLLM disk cache: {e2}. Caching is disabled.")
293
299
  litellm.cache = None
294
300
 
295
301
  if not cache_configured:
@@ -852,6 +858,10 @@ def llm_invoke(
852
858
  # --- 3. Iterate Through Candidates and Invoke LLM ---
853
859
  last_exception = None
854
860
  newly_acquired_keys: Dict[str, bool] = {} # Track keys obtained in this run
861
+
862
+ # Initialize variables for retry section
863
+ response_format = None
864
+ time_kwargs = {}
855
865
 
856
866
  for model_info in candidate_models:
857
867
  model_name_litellm = model_info['model']
@@ -964,7 +974,8 @@ def llm_invoke(
964
974
  logger.info(f"[INFO] Requesting structured output (Pydantic: {output_pydantic.__name__}) for {model_name_litellm}")
965
975
  # Pass the Pydantic model directly if supported, else use json_object
966
976
  # LiteLLM handles passing Pydantic models for supported providers
967
- litellm_kwargs["response_format"] = output_pydantic
977
+ response_format = output_pydantic
978
+ litellm_kwargs["response_format"] = response_format
968
979
  # As a fallback, one could use:
969
980
  # litellm_kwargs["response_format"] = {"type": "json_object"}
970
981
  # And potentially enable client-side validation:
@@ -986,7 +997,9 @@ def llm_invoke(
986
997
  # Currently known: Anthropic uses 'thinking'
987
998
  # Model name comparison is more robust than provider string
988
999
  if provider == 'anthropic': # Check provider column instead of model prefix
989
- litellm_kwargs["thinking"] = {"type": "enabled", "budget_tokens": budget}
1000
+ thinking_param = {"type": "enabled", "budget_tokens": budget}
1001
+ litellm_kwargs["thinking"] = thinking_param
1002
+ time_kwargs["thinking"] = thinking_param
990
1003
  if verbose:
991
1004
  logger.info(f"[INFO] Requesting Anthropic thinking (budget type) with budget: {budget} tokens for {model_name_litellm}")
992
1005
  else:
@@ -1006,6 +1019,7 @@ def llm_invoke(
1006
1019
  effort = "medium"
1007
1020
  # Use the common 'reasoning_effort' param LiteLLM provides
1008
1021
  litellm_kwargs["reasoning_effort"] = effort
1022
+ time_kwargs["reasoning_effort"] = effort
1009
1023
  if verbose:
1010
1024
  logger.info(f"[INFO] Requesting reasoning_effort='{effort}' (effort type) for {model_name_litellm} based on time={time}")
1011
1025
 
pdd/sync_orchestration.py CHANGED
@@ -17,6 +17,9 @@ from dataclasses import asdict
17
17
 
18
18
  import click
19
19
 
20
+ # --- Constants ---
21
+ MAX_CONSECUTIVE_TESTS = 3 # Allow up to 3 consecutive test attempts
22
+
20
23
  # --- Real PDD Component Imports ---
21
24
  from .sync_animation import sync_animation
22
25
  from .sync_determine_operation import (
@@ -533,6 +536,27 @@ def sync_orchestration(
533
536
  })
534
537
  break
535
538
 
539
+ # Detect consecutive test operations (infinite test loop protection)
540
+ if operation == 'test':
541
+ # Count consecutive test operations
542
+ consecutive_tests = 0
543
+ for i in range(len(operation_history) - 1, -1, -1):
544
+ if operation_history[i] == 'test':
545
+ consecutive_tests += 1
546
+ else:
547
+ break
548
+
549
+ # Use module-level constant for max consecutive test attempts
550
+ if consecutive_tests >= MAX_CONSECUTIVE_TESTS:
551
+ errors.append(f"Detected {consecutive_tests} consecutive test operations. Breaking infinite test loop.")
552
+ errors.append("Coverage target may not be achievable with additional test generation.")
553
+ log_sync_event(basename, language, "cycle_detected", {
554
+ "cycle_type": "consecutive-test",
555
+ "consecutive_count": consecutive_tests,
556
+ "operation_history": operation_history[-10:] # Last 10 operations
557
+ })
558
+ break
559
+
536
560
  if operation in ['all_synced', 'nothing', 'fail_and_request_manual_merge', 'error', 'analyze_conflict']:
537
561
  current_function_name_ref[0] = "synced" if operation in ['all_synced', 'nothing'] else "conflict"
538
562
 
@@ -1024,10 +1048,14 @@ def sync_orchestration(
1024
1048
  success = result.get('success', False)
1025
1049
  current_cost_ref[0] += result.get('cost', 0.0)
1026
1050
  elif isinstance(result, tuple) and len(result) >= 3:
1027
- # Tuple return (e.g., from code_generator_main, context_generator_main)
1028
- # For tuples, success is determined by no exceptions and valid return content
1029
- # Check if the first element (generated content) is None, which indicates failure
1030
- success = result[0] is not None
1051
+ # Tuple return (e.g., from code_generator_main, context_generator_main, cmd_test_main)
1052
+ # For test operations, use file existence as success criteria to match local detection
1053
+ if operation == 'test':
1054
+ success = pdd_files['test'].exists()
1055
+ else:
1056
+ # For other operations, success is determined by valid return content
1057
+ # Check if the first element (generated content) is None, which indicates failure
1058
+ success = result[0] is not None
1031
1059
  # Extract cost from tuple (usually second-to-last element)
1032
1060
  cost = result[-2] if len(result) >= 2 and isinstance(result[-2], (int, float)) else 0.0
1033
1061
  current_cost_ref[0] += cost
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdd-cli
3
- Version: 0.0.48
3
+ Version: 0.0.49
4
4
  Summary: PDD (Prompt-Driven Development) Command Line Interface
5
5
  Author: Greg Tanaka
6
6
  Author-email: glt@alumni.caltech.edu
@@ -31,13 +31,14 @@ Requires-Dist: nest_asyncio==1.6.0
31
31
  Requires-Dist: pandas==2.2.3
32
32
  Requires-Dist: psutil==5.9.0
33
33
  Requires-Dist: pydantic==2.11.2
34
- Requires-Dist: litellm
34
+ Requires-Dist: litellm[caching]>=1.75.5
35
35
  Requires-Dist: rich==14.0.0
36
36
  Requires-Dist: semver==3.0.2
37
37
  Requires-Dist: setuptools
38
38
  Requires-Dist: pytest
39
39
  Requires-Dist: boto3==1.35.99
40
40
  Requires-Dist: python-Levenshtein
41
+ Requires-Dist: openai>=1.99.5
41
42
  Provides-Extra: dev
42
43
  Requires-Dist: commitizen; extra == "dev"
43
44
  Requires-Dist: pytest-cov; extra == "dev"
@@ -46,7 +47,7 @@ Requires-Dist: pytest-asyncio; extra == "dev"
46
47
  Requires-Dist: z3-solver; extra == "dev"
47
48
  Dynamic: license-file
48
49
 
49
- .. image:: https://img.shields.io/badge/pdd--cli-v0.0.48-blue
50
+ .. image:: https://img.shields.io/badge/pdd--cli-v0.0.49-blue
50
51
  :alt: PDD-CLI Version
51
52
 
52
53
  .. image:: https://img.shields.io/badge/Discord-join%20chat-7289DA.svg?logo=discord&logoColor=white&link=https://discord.gg/Yp4RTh8bG7
@@ -123,7 +124,7 @@ After installation, verify:
123
124
 
124
125
  pdd --version
125
126
 
126
- You'll see the current PDD version (e.g., 0.0.48).
127
+ You'll see the current PDD version (e.g., 0.0.49).
127
128
 
128
129
  Getting Started with Examples
129
130
  -----------------------------
@@ -1,4 +1,4 @@
1
- pdd/__init__.py,sha256=3Kpl2xH2n48yKRBqi0uINNAJzGIYcS9IG-BNFpdP3QA,634
1
+ pdd/__init__.py,sha256=XJgiiw7J4yF8hdCjnIIweAshNfxsBs1CSWV_5_BD3x0,634
2
2
  pdd/auto_deps_main.py,sha256=iV2khcgSejiXjh5hiQqeu_BJQOLfTKXhMx14j6vRlf8,3916
3
3
  pdd/auto_include.py,sha256=OJcdcwTwJNqHPHKG9P4m9Ij-PiLex0EbuwJP0uiQi_Y,7484
4
4
  pdd/auto_update.py,sha256=w6jzTnMiYRNpwQHQxWNiIAwQ0d6xh1iOB3xgDsabWtc,5236
@@ -41,7 +41,7 @@ pdd/increase_tests.py,sha256=68cM9d1CpaLLm2ISFpJw39xbRjsfwxwS06yAwRoUCHk,4433
41
41
  pdd/incremental_code_generator.py,sha256=cWo3DJ0PybnrepFEAMibGjTVY3T8mLVvPt5W8cNhuxU,9402
42
42
  pdd/insert_includes.py,sha256=hNn8muRULiq3YMNI4W4pEPeM1ckiZ-EgR9WtCyWQ1eQ,5533
43
43
  pdd/install_completion.py,sha256=bLMJuMOBDvsEnDAUpgiPesNRGhY_IvBvz8ZvmbTzP4o,5472
44
- pdd/llm_invoke.py,sha256=MDPt7Pl3IVZKyThEcpE_r9WVBEkrzrjoMP_EYKrJb84,75318
44
+ pdd/llm_invoke.py,sha256=B5DwM4x8N191ehklb_WwahFiNBjEVKFcp8RPetWZl3Y,75892
45
45
  pdd/load_prompt_template.py,sha256=4NH8_t5eon_vcyTznqtemJ_yAPkTJm_hSdTRgzj3qEQ,1907
46
46
  pdd/logo_animation.py,sha256=n6HJWzuFze2csAAW2-zbxfjvWFYRI4hIdwVBtHBOkj4,20782
47
47
  pdd/mcp_config.json,sha256=D3ctWHlShvltbtH37zbYb6smVE0V80_lGjDKDIqsSBE,124
@@ -61,7 +61,7 @@ pdd/summarize_directory.py,sha256=cRKIVRWcti9SGLDuc40tsNbho7CdVbpWhlI-PoVC7xI,95
61
61
  pdd/sync_animation.py,sha256=e7Qb4m70BHYpl37CuuF-95j-APctPL4Zm_o1PSTTRFQ,28070
62
62
  pdd/sync_determine_operation.py,sha256=16Co4_IE0AZBLPdICi2MqW3730hiyLdqOf2kZcQA2cc,59590
63
63
  pdd/sync_main.py,sha256=2XUZZL9oIiNVsVohdsMpvrNoV8XkXhEKyt5bb2HlNHI,13641
64
- pdd/sync_orchestration.py,sha256=Uhe0W89i9bGKnkwHlRWe9wBfn5z18njbXXKdXGZfj2w,66715
64
+ pdd/sync_orchestration.py,sha256=FizZkwWPj30WCRVZIVKoyRXR3IxTC0LbcroMenq3xlQ,68320
65
65
  pdd/trace.py,sha256=oXHbOMfxeso7m81N5V2ixS_l6BPAlZrH6vifn0IgWbo,5225
66
66
  pdd/trace_main.py,sha256=Z8m8UgRZoaojX_H6aDDU7_lB7WNCLwZpFxbPTm1s-6s,4902
67
67
  pdd/track_cost.py,sha256=VIrHYh4i2G5T5Dq1plxwuzsG4OrHQgO0GPgFckgsQ_4,3266
@@ -108,9 +108,9 @@ pdd/prompts/trim_results_start_LLM.prompt,sha256=OKz8fAf1cYWKWgslFOHEkUpfaUDARh3
108
108
  pdd/prompts/unfinished_prompt_LLM.prompt,sha256=-JgBpiPTQZdWOAwOG1XpfpD9waynFTAT3Jo84eQ4bTw,1543
109
109
  pdd/prompts/update_prompt_LLM.prompt,sha256=prIc8uLp2jqnLTHt6JvWDZGanPZipivhhYeXe0lVaYw,1328
110
110
  pdd/prompts/xml_convertor_LLM.prompt,sha256=YGRGXJeg6EhM9690f-SKqQrKqSJjLFD51UrPOlO0Frg,2786
111
- pdd_cli-0.0.48.dist-info/licenses/LICENSE,sha256=-1bjYH-CEjGEQ8VixtnRYuu37kN6F9NxmZSDkBuUQ9o,1062
112
- pdd_cli-0.0.48.dist-info/METADATA,sha256=DRblBGmVC4swRCPJQnbScurcHpabllEdfTWZpjxBWdI,12399
113
- pdd_cli-0.0.48.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
114
- pdd_cli-0.0.48.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
115
- pdd_cli-0.0.48.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
116
- pdd_cli-0.0.48.dist-info/RECORD,,
111
+ pdd_cli-0.0.49.dist-info/licenses/LICENSE,sha256=-1bjYH-CEjGEQ8VixtnRYuu37kN6F9NxmZSDkBuUQ9o,1062
112
+ pdd_cli-0.0.49.dist-info/METADATA,sha256=oOFDn3p_wev8d-q6JuhsPX6UQpdzN9Hb5feLaP7xEx0,12446
113
+ pdd_cli-0.0.49.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
114
+ pdd_cli-0.0.49.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
115
+ pdd_cli-0.0.49.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
116
+ pdd_cli-0.0.49.dist-info/RECORD,,