pdd-cli 0.0.55__py3-none-any.whl → 0.0.56__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.55"
3
+ __version__ = "0.0.56"
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/auto_deps_main.py CHANGED
@@ -49,7 +49,8 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
49
49
  force=ctx.obj.get('force', False),
50
50
  quiet=ctx.obj.get('quiet', False),
51
51
  command="auto-deps",
52
- command_options=command_options
52
+ command_options=command_options,
53
+ context_override=ctx.obj.get('context')
53
54
  )
54
55
 
55
56
  # Get the CSV file path
@@ -101,4 +102,4 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
101
102
  except Exception as exc:
102
103
  if not ctx.obj.get('quiet', False):
103
104
  rprint(f"[bold red]Error:[/bold red] {str(exc)}")
104
- sys.exit(1)
105
+ sys.exit(1)
pdd/bug_main.py CHANGED
@@ -50,7 +50,8 @@ def bug_main(
50
50
  force=ctx.obj.get('force', False),
51
51
  quiet=ctx.obj.get('quiet', False),
52
52
  command="bug",
53
- command_options=command_options
53
+ command_options=command_options,
54
+ context_override=ctx.obj.get('context')
54
55
  )
55
56
 
56
57
  # Use the language detected by construct_paths if none was explicitly provided
@@ -117,4 +118,4 @@ def bug_main(
117
118
  except Exception as e:
118
119
  if not ctx.obj.get('quiet', False):
119
120
  rprint(f"[bold red]Error:[/bold red] {str(e)}")
120
- sys.exit(1)
121
+ sys.exit(1)
pdd/change_main.py CHANGED
@@ -203,6 +203,7 @@ def change_main(
203
203
  quiet=quiet,
204
204
  command="change",
205
205
  command_options=command_options,
206
+ context_override=ctx.obj.get('context')
206
207
  )
207
208
  logger.debug("construct_paths returned:")
208
209
  logger.debug(" input_strings keys: %s", list(input_strings.keys()))
pdd/cli.py CHANGED
@@ -26,7 +26,7 @@ from .cmd_test_main import cmd_test_main
26
26
  from .code_generator_main import code_generator_main
27
27
  from .conflicts_main import conflicts_main
28
28
  # Need to import construct_paths for tests patching pdd.cli.construct_paths
29
- from .construct_paths import construct_paths
29
+ from .construct_paths import construct_paths, list_available_contexts
30
30
  from .context_generator_main import context_generator_main
31
31
  from .crash_main import crash_main
32
32
  from .detect_change_main import detect_change_main
@@ -76,7 +76,7 @@ def handle_error(exception: Exception, command_name: str, quiet: bool):
76
76
 
77
77
 
78
78
  # --- Main CLI Group ---
79
- @click.group(chain=True, help="PDD (Prompt-Driven Development) Command Line Interface.")
79
+ @click.group(chain=True, invoke_without_command=True, help="PDD (Prompt-Driven Development) Command Line Interface.")
80
80
  @click.option(
81
81
  "--force",
82
82
  is_flag=True,
@@ -134,6 +134,20 @@ def handle_error(exception: Exception, command_name: str, quiet: bool):
134
134
  default=False,
135
135
  help="Run commands locally instead of in the cloud.",
136
136
  )
137
+ @click.option(
138
+ "--context",
139
+ "context_override",
140
+ type=str,
141
+ default=None,
142
+ help="Override automatic context detection and use the specified .pddrc context.",
143
+ )
144
+ @click.option(
145
+ "--list-contexts",
146
+ "list_contexts",
147
+ is_flag=True,
148
+ default=False,
149
+ help="List available contexts from .pddrc and exit.",
150
+ )
137
151
  @click.version_option(version=__version__, package_name="pdd-cli")
138
152
  @click.pass_context
139
153
  def cli(
@@ -147,6 +161,8 @@ def cli(
147
161
  review_examples: bool,
148
162
  local: bool,
149
163
  time: Optional[float], # Type hint is Optional[float]
164
+ context_override: Optional[str],
165
+ list_contexts: bool,
150
166
  ):
151
167
  """
152
168
  Main entry point for the PDD CLI. Handles global options and initializes context.
@@ -166,11 +182,37 @@ def cli(
166
182
  ctx.obj["local"] = local
167
183
  # Use DEFAULT_TIME if time is not provided
168
184
  ctx.obj["time"] = time if time is not None else DEFAULT_TIME
185
+ # Persist context override for downstream calls
186
+ ctx.obj["context"] = context_override
169
187
 
170
188
  # Suppress verbose if quiet is enabled
171
189
  if quiet:
172
190
  ctx.obj["verbose"] = False
173
191
 
192
+ # If --list-contexts is provided, print and exit before any other actions
193
+ if list_contexts:
194
+ try:
195
+ names = list_available_contexts()
196
+ except Exception as exc:
197
+ # Surface config errors as usage errors
198
+ raise click.UsageError(f"Failed to load .pddrc: {exc}")
199
+ # Print one per line; avoid Rich formatting for portability
200
+ for name in names:
201
+ click.echo(name)
202
+ ctx.exit(0)
203
+
204
+ # Optional early validation for --context
205
+ if context_override:
206
+ try:
207
+ names = list_available_contexts()
208
+ except Exception as exc:
209
+ # If .pddrc is malformed, propagate as usage error
210
+ raise click.UsageError(f"Failed to load .pddrc: {exc}")
211
+ if context_override not in names:
212
+ raise click.UsageError(
213
+ f"Unknown context '{context_override}'. Available contexts: {', '.join(names)}"
214
+ )
215
+
174
216
  # Perform auto-update check unless disabled
175
217
  if os.getenv("PDD_AUTO_UPDATE", "true").lower() != "false":
176
218
  try:
pdd/cmd_test_main.py CHANGED
@@ -88,6 +88,7 @@ def cmd_test_main(
88
88
  quiet=ctx.obj["quiet"],
89
89
  command="test",
90
90
  command_options=command_options,
91
+ context_override=ctx.obj.get('context')
91
92
  )
92
93
  except Exception as exception:
93
94
  # Catching a general exception is necessary here to handle a wide range of
@@ -184,6 +184,7 @@ def code_generator_main(
184
184
  quiet=quiet,
185
185
  command="generate",
186
186
  command_options=command_options,
187
+ context_override=ctx.obj.get('context')
187
188
  )
188
189
  prompt_content = input_strings["prompt_file"]
189
190
  # Determine final output path: if user passed a directory, use resolved file path
pdd/conflicts_main.py CHANGED
@@ -33,7 +33,8 @@ def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optio
33
33
  force=ctx.obj.get('force', False),
34
34
  quiet=ctx.obj.get('quiet', False),
35
35
  command="conflicts",
36
- command_options=command_options
36
+ command_options=command_options,
37
+ context_override=ctx.obj.get('context')
37
38
  )
38
39
 
39
40
  # Load input files
@@ -91,4 +92,4 @@ def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optio
91
92
  except Exception as e:
92
93
  if not ctx.obj.get('quiet', False):
93
94
  rprint(f"[bold red]Error:[/bold red] {str(e)}")
94
- sys.exit(1)
95
+ sys.exit(1)
pdd/construct_paths.py CHANGED
@@ -56,6 +56,23 @@ def _load_pddrc_config(pddrc_path: Path) -> Dict[str, Any]:
56
56
  except Exception as e:
57
57
  raise ValueError(f"Error loading .pddrc: {e}")
58
58
 
59
+ def list_available_contexts(start_path: Optional[Path] = None) -> list[str]:
60
+ """Return sorted context names from the nearest .pddrc.
61
+
62
+ - Searches upward from `start_path` (or CWD) for a `.pddrc` file.
63
+ - If found, loads and validates it, then returns sorted context names.
64
+ - If no `.pddrc` exists, returns ["default"].
65
+ - Propagates ValueError for malformed `.pddrc` to allow callers to render
66
+ helpful errors.
67
+ """
68
+ pddrc = _find_pddrc_file(start_path)
69
+ if not pddrc:
70
+ return ["default"]
71
+ config = _load_pddrc_config(pddrc)
72
+ contexts = config.get("contexts", {})
73
+ names = sorted(contexts.keys()) if isinstance(contexts, dict) else []
74
+ return names or ["default"]
75
+
59
76
  def _detect_context(current_dir: Path, config: Dict[str, Any], context_override: Optional[str] = None) -> Optional[str]:
60
77
  """Detect the appropriate context based on current directory path."""
61
78
  if context_override:
@@ -31,7 +31,8 @@ def context_generator_main(ctx: click.Context, prompt_file: str, code_file: str,
31
31
  force=ctx.obj.get('force', False),
32
32
  quiet=ctx.obj.get('quiet', False),
33
33
  command="example",
34
- command_options=command_options
34
+ command_options=command_options,
35
+ context_override=ctx.obj.get('context')
35
36
  )
36
37
 
37
38
  # Load input files
pdd/crash_main.py CHANGED
@@ -77,7 +77,8 @@ def crash_main(
77
77
  force=force,
78
78
  quiet=quiet,
79
79
  command="crash",
80
- command_options=command_options
80
+ command_options=command_options,
81
+ context_override=ctx.obj.get('context')
81
82
  )
82
83
 
83
84
  prompt_content = input_strings["prompt_file"]
@@ -177,4 +178,4 @@ def crash_main(
177
178
  except Exception as e:
178
179
  if not quiet:
179
180
  rprint(f"[bold red]An unexpected error occurred:[/bold red] {str(e)}")
180
- sys.exit(1)
181
+ sys.exit(1)
@@ -60,4 +60,5 @@ LLM,del,.prompt
60
60
  prompt,del,.prompt
61
61
  TOML,#,.toml
62
62
  Log,del,.log
63
- reStructuredText,del,.rst
63
+ reStructuredText,del,.rst
64
+ Text,del,.txt
pdd/detect_change_main.py CHANGED
@@ -44,7 +44,8 @@ def detect_change_main(
44
44
  force=ctx.obj.get('force', False),
45
45
  quiet=ctx.obj.get('quiet', False),
46
46
  command="detect",
47
- command_options=command_options
47
+ command_options=command_options,
48
+ context_override=ctx.obj.get('context')
48
49
  )
49
50
 
50
51
  # Get change description content
@@ -100,4 +101,4 @@ def detect_change_main(
100
101
  except Exception as e:
101
102
  if not ctx.obj.get('quiet', False):
102
103
  rprint(f"[bold red]Error:[/bold red] {str(e)}")
103
- sys.exit(1)
104
+ sys.exit(1)
pdd/fix_main.py CHANGED
@@ -97,7 +97,8 @@ def fix_main(
97
97
  quiet=ctx.obj.get('quiet', False),
98
98
  command="fix",
99
99
  command_options=command_options,
100
- create_error_file=loop # Only create error file if in loop mode
100
+ create_error_file=loop, # Only create error file if in loop mode
101
+ context_override=ctx.obj.get('context')
101
102
  )
102
103
 
103
104
  # Get parameters from context
@@ -296,4 +297,4 @@ def fix_main(
296
297
  # Print other errors normally, escaping the error string
297
298
  from rich.markup import escape # Ensure escape is imported
298
299
  rprint(f"[bold red]Error:[/bold red] {escape(str(e))}")
299
- sys.exit(1)
300
+ sys.exit(1)
@@ -204,6 +204,7 @@ def fix_verification_main(
204
204
  quiet=quiet,
205
205
  command="verify",
206
206
  command_options=command_options,
207
+ context_override=ctx.obj.get('context')
207
208
  )
208
209
  output_code_path = output_file_paths.get("output_code")
209
210
  output_results_path = output_file_paths.get("output_results")
pdd/preprocess_main.py CHANGED
@@ -33,6 +33,7 @@ def preprocess_main(
33
33
  quiet=ctx.obj.get("quiet", False),
34
34
  command="preprocess",
35
35
  command_options=command_options,
36
+ context_override=ctx.obj.get('context')
36
37
  )
37
38
 
38
39
  # Load prompt file
@@ -76,4 +77,4 @@ def preprocess_main(
76
77
  except Exception as e:
77
78
  if not ctx.obj.get("quiet", False):
78
79
  rprint(f"[bold red]Error during preprocessing:[/bold red] {e}")
79
- sys.exit(1)
80
+ sys.exit(1)
pdd/split_main.py CHANGED
@@ -53,7 +53,8 @@ def split_main(
53
53
  force=ctx.obj.get('force', False),
54
54
  quiet=ctx.obj.get('quiet', False),
55
55
  command="split",
56
- command_options=command_options
56
+ command_options=command_options,
57
+ context_override=ctx.obj.get('context')
57
58
  )
58
59
 
59
60
  # Get parameters from context
@@ -113,4 +114,4 @@ def split_main(
113
114
  elif isinstance(e, ValueError):
114
115
  rprint("[yellow]Hint: Check if input files have valid content.[/yellow]")
115
116
 
116
- sys.exit(1)
117
+ sys.exit(1)
@@ -209,7 +209,7 @@ def get_extension(language: str) -> str:
209
209
  return extensions.get(language.lower(), language.lower())
210
210
 
211
211
 
212
- def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts") -> Dict[str, Path]:
212
+ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts", context_override: Optional[str] = None) -> Dict[str, Path]:
213
213
  """Returns a dictionary mapping file types to their expected Path objects."""
214
214
  import logging
215
215
  logger = logging.getLogger(__name__)
@@ -233,7 +233,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
233
233
  force=True,
234
234
  quiet=True,
235
235
  command="sync",
236
- command_options={"basename": basename, "language": language}
236
+ command_options={"basename": basename, "language": language},
237
+ context_override=context_override
237
238
  )
238
239
 
239
240
  import logging
@@ -299,7 +300,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
299
300
  force=True, # Use force=True to avoid interactive prompts during sync
300
301
  quiet=True,
301
302
  command="sync", # Use sync command to get more tolerant path handling
302
- command_options={"basename": basename, "language": language}
303
+ command_options={"basename": basename, "language": language},
304
+ context_override=context_override
303
305
  )
304
306
 
305
307
  # For sync command, output_file_paths contains the configured paths
@@ -332,7 +334,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
332
334
  # Get example path using example command
333
335
  _, _, example_output_paths, _ = construct_paths(
334
336
  input_file_paths={"prompt_file": prompt_path, "code_file": code_path},
335
- force=True, quiet=True, command="example", command_options={}
337
+ force=True, quiet=True, command="example", command_options={},
338
+ context_override=context_override
336
339
  )
337
340
  example_path = Path(example_output_paths.get('output', f"{basename}_example.{get_extension(language)}"))
338
341
 
@@ -340,7 +343,8 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
340
343
  try:
341
344
  _, _, test_output_paths, _ = construct_paths(
342
345
  input_file_paths={"prompt_file": prompt_path, "code_file": code_path},
343
- force=True, quiet=True, command="test", command_options={}
346
+ force=True, quiet=True, command="test", command_options={},
347
+ context_override=context_override
344
348
  )
345
349
  test_path = Path(test_output_paths.get('output', f"test_{basename}.{get_extension(language)}"))
346
350
  except FileNotFoundError:
@@ -365,14 +369,16 @@ def get_pdd_file_paths(basename: str, language: str, prompts_dir: str = "prompts
365
369
  # Get configured directories by using construct_paths with just the prompt file
366
370
  _, _, example_output_paths, _ = construct_paths(
367
371
  input_file_paths={"prompt_file": prompt_path},
368
- force=True, quiet=True, command="example", command_options={}
372
+ force=True, quiet=True, command="example", command_options={},
373
+ context_override=context_override
369
374
  )
370
375
  example_path = Path(example_output_paths.get('output', f"{basename}_example.{get_extension(language)}"))
371
376
 
372
377
  try:
373
378
  _, _, test_output_paths, _ = construct_paths(
374
379
  input_file_paths={"prompt_file": prompt_path},
375
- force=True, quiet=True, command="test", command_options={}
380
+ force=True, quiet=True, command="test", command_options={},
381
+ context_override=context_override
376
382
  )
377
383
  test_path = Path(test_output_paths.get('output', f"test_{basename}.{get_extension(language)}"))
378
384
  except Exception:
@@ -768,7 +774,7 @@ def _check_example_success_history(basename: str, language: str) -> bool:
768
774
  return False
769
775
 
770
776
 
771
- def sync_determine_operation(basename: str, language: str, target_coverage: float, budget: float = 10.0, log_mode: bool = False, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False) -> SyncDecision:
777
+ def sync_determine_operation(basename: str, language: str, target_coverage: float, budget: float = 10.0, log_mode: bool = False, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False, context_override: Optional[str] = None) -> SyncDecision:
772
778
  """
773
779
  Core decision-making function for sync operations with skip flag awareness.
774
780
 
@@ -788,14 +794,14 @@ def sync_determine_operation(basename: str, language: str, target_coverage: floa
788
794
 
789
795
  if log_mode:
790
796
  # Skip locking for read-only analysis
791
- return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify)
797
+ return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify, context_override)
792
798
  else:
793
799
  # Normal exclusive locking for actual operations
794
800
  with SyncLock(basename, language) as lock:
795
- return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify)
801
+ return _perform_sync_analysis(basename, language, target_coverage, budget, prompts_dir, skip_tests, skip_verify, context_override)
796
802
 
797
803
 
798
- def _perform_sync_analysis(basename: str, language: str, target_coverage: float, budget: float, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False) -> SyncDecision:
804
+ def _perform_sync_analysis(basename: str, language: str, target_coverage: float, budget: float, prompts_dir: str = "prompts", skip_tests: bool = False, skip_verify: bool = False, context_override: Optional[str] = None) -> SyncDecision:
799
805
  """
800
806
  Perform the sync state analysis without locking concerns.
801
807
 
@@ -846,7 +852,7 @@ def _perform_sync_analysis(basename: str, language: str, target_coverage: float,
846
852
  # Check test failures (after crash verification check)
847
853
  if run_report.tests_failed > 0:
848
854
  # First check if the test file actually exists
849
- pdd_files = get_pdd_file_paths(basename, language, prompts_dir)
855
+ pdd_files = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
850
856
  test_file = pdd_files.get('test')
851
857
 
852
858
  # Only suggest 'fix' if test file exists
@@ -945,7 +951,7 @@ def _perform_sync_analysis(basename: str, language: str, target_coverage: float,
945
951
  )
946
952
 
947
953
  # 2. Analyze File State
948
- paths = get_pdd_file_paths(basename, language, prompts_dir)
954
+ paths = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
949
955
  current_hashes = calculate_current_hashes(paths)
950
956
 
951
957
  # 3. Implement the Decision Tree
@@ -1264,7 +1270,14 @@ def _perform_sync_analysis(basename: str, language: str, target_coverage: float,
1264
1270
  )
1265
1271
 
1266
1272
 
1267
- def analyze_conflict_with_llm(basename: str, language: str, fingerprint: Fingerprint, changed_files: List[str], prompts_dir: str = "prompts") -> SyncDecision:
1273
+ def analyze_conflict_with_llm(
1274
+ basename: str,
1275
+ language: str,
1276
+ fingerprint: Fingerprint,
1277
+ changed_files: List[str],
1278
+ prompts_dir: str = "prompts",
1279
+ context_override: Optional[str] = None,
1280
+ ) -> SyncDecision:
1268
1281
  """
1269
1282
  Resolve complex sync conflicts using an LLM.
1270
1283
 
@@ -1297,7 +1310,7 @@ def analyze_conflict_with_llm(basename: str, language: str, fingerprint: Fingerp
1297
1310
  )
1298
1311
 
1299
1312
  # 2. Gather file paths and diffs
1300
- paths = get_pdd_file_paths(basename, language, prompts_dir)
1313
+ paths = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
1301
1314
 
1302
1315
  # Generate diffs for changed files
1303
1316
  diffs = {}
pdd/sync_main.py CHANGED
@@ -192,6 +192,7 @@ def sync_main(
192
192
  log=True,
193
193
  verbose=verbose,
194
194
  quiet=quiet,
195
+ context_override=context_override,
195
196
  )
196
197
  return {}, 0.0, ""
197
198
 
@@ -280,6 +281,7 @@ def sync_main(
280
281
  review_examples=review_examples,
281
282
  local=local,
282
283
  context_config=resolved_config,
284
+ context_override=context_override,
283
285
  )
284
286
 
285
287
  lang_cost = sync_result.get("total_cost", 0.0)
@@ -330,4 +332,4 @@ def sync_main(
330
332
  aggregated_results["total_cost"] = total_cost
331
333
  aggregated_results["primary_model"] = primary_model
332
334
 
333
- return aggregated_results, total_cost, primary_model
335
+ return aggregated_results, total_cost, primary_model
pdd/sync_orchestration.py CHANGED
@@ -341,6 +341,7 @@ def sync_orchestration(
341
341
  review_examples: bool = False,
342
342
  local: bool = False,
343
343
  context_config: Optional[Dict[str, str]] = None,
344
+ context_override: Optional[str] = None,
344
345
  ) -> Dict[str, Any]:
345
346
  """
346
347
  Orchestrates the complete PDD sync workflow with parallel animation.
@@ -358,7 +359,7 @@ def sync_orchestration(
358
359
 
359
360
  # --- Initialize State and Paths ---
360
361
  try:
361
- pdd_files = get_pdd_file_paths(basename, language, prompts_dir)
362
+ pdd_files = get_pdd_file_paths(basename, language, prompts_dir, context_override=context_override)
362
363
  # Debug: Print the paths we got
363
364
  print(f"DEBUG: get_pdd_file_paths returned:")
364
365
  print(f" test: {pdd_files.get('test', 'N/A')}")
@@ -457,7 +458,7 @@ def sync_orchestration(
457
458
  "percentage": (budget_remaining / budget) * 100
458
459
  })
459
460
 
460
- decision = sync_determine_operation(basename, language, target_coverage, budget_remaining, False, prompts_dir, skip_tests, skip_verify)
461
+ decision = sync_determine_operation(basename, language, target_coverage, budget_remaining, False, prompts_dir, skip_tests, skip_verify, context_override)
461
462
  operation = decision.operation
462
463
 
463
464
  # Create log entry with decision info
pdd/trace_main.py CHANGED
@@ -39,7 +39,8 @@ def trace_main(ctx: click.Context, prompt_file: str, code_file: str, code_line:
39
39
  force=ctx.obj.get('force', False),
40
40
  quiet=quiet,
41
41
  command="trace",
42
- command_options=command_options
42
+ command_options=command_options,
43
+ context_override=ctx.obj.get('context')
43
44
  )
44
45
  logger.debug("File paths constructed successfully")
45
46
 
pdd/update_main.py CHANGED
@@ -48,6 +48,7 @@ def update_main(
48
48
  quiet=ctx.obj.get("quiet", False),
49
49
  command="update",
50
50
  command_options=command_options,
51
+ context_override=ctx.obj.get('context')
51
52
  )
52
53
 
53
54
  # Extract input strings
@@ -101,4 +102,4 @@ def update_main(
101
102
  except Exception as e:
102
103
  if not ctx.obj.get("quiet", False):
103
104
  rprint(f"[bold red]Error:[/bold red] {str(e)}")
104
- sys.exit(1)
105
+ sys.exit(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdd-cli
3
- Version: 0.0.55
3
+ Version: 0.0.56
4
4
  Summary: PDD (Prompt-Driven Development) Command Line Interface
5
5
  Author: Greg Tanaka
6
6
  Author-email: glt@alumni.caltech.edu
@@ -51,7 +51,7 @@ Requires-Dist: build; extra == "dev"
51
51
  Requires-Dist: twine; extra == "dev"
52
52
  Dynamic: license-file
53
53
 
54
- .. image:: https://img.shields.io/badge/pdd--cli-v0.0.55-blue
54
+ .. image:: https://img.shields.io/badge/pdd--cli-v0.0.56-blue
55
55
  :alt: PDD-CLI Version
56
56
 
57
57
  .. image:: https://img.shields.io/badge/Discord-join%20chat-7289DA.svg?logo=discord&logoColor=white&link=https://discord.gg/Yp4RTh8bG7
@@ -128,7 +128,7 @@ After installation, verify:
128
128
 
129
129
  pdd --version
130
130
 
131
- You'll see the current PDD version (e.g., 0.0.55).
131
+ You'll see the current PDD version (e.g., 0.0.56).
132
132
 
133
133
  Getting Started with Examples
134
134
  -----------------------------
@@ -1,35 +1,35 @@
1
- pdd/__init__.py,sha256=8100eVNrSFeW_1cEQnyzi8_VJRy0ugsp5qEgZxrIYI4,633
2
- pdd/auto_deps_main.py,sha256=iV2khcgSejiXjh5hiQqeu_BJQOLfTKXhMx14j6vRlf8,3916
1
+ pdd/__init__.py,sha256=ca8MfVovv1zfjBoDhLPWEWu1bOMwbT7XY3CcRF635Sg,633
2
+ pdd/auto_deps_main.py,sha256=cpP3bbzVL3jomrGinpzTxzIDIC8tmDDYOwUAC1TKRaw,3970
3
3
  pdd/auto_include.py,sha256=OJcdcwTwJNqHPHKG9P4m9Ij-PiLex0EbuwJP0uiQi_Y,7484
4
4
  pdd/auto_update.py,sha256=w6jzTnMiYRNpwQHQxWNiIAwQ0d6xh1iOB3xgDsabWtc,5236
5
- pdd/bug_main.py,sha256=INFWwD3TU00cBmTqFcScAoK25LsZE1zkinmnSM7ElS0,4787
5
+ pdd/bug_main.py,sha256=EtaGTuucQ7VgqOhyg4o6GFG7_QtTsDPTrRdGJWT648M,4841
6
6
  pdd/bug_to_unit_test.py,sha256=BoQqNyKQpBQDW8-JwBH_RX4RHRSiU8Kk3EplFrkECt0,6665
7
7
  pdd/change.py,sha256=Hg_x0pa370-e6oDiczaTgFAy3Am9ReCPkqFrvqv4U38,6114
8
- pdd/change_main.py,sha256=oTQz9DUy6pIqq5CJzHIk01NrC88Xrm4FNEu0e-1Hx5Y,27748
9
- pdd/cli.py,sha256=qEUKzReooccQGIUNvoWAqMagW3NpbWZ63iyqToYgnyg,45299
10
- pdd/cmd_test_main.py,sha256=5ftxDNNklDlHodkW8Rluvo3NKMHyMNhumG7G8mSoM9g,7716
8
+ pdd/change_main.py,sha256=04VHiO_D-jlfeRn6rrVH7ZTA5agXPoJGm1StGI8--XY,27804
9
+ pdd/cli.py,sha256=njGVezstZGTeinhrUdOQ2K21Wpt1jiA5jU6BT7OZpaY,46782
10
+ pdd/cmd_test_main.py,sha256=M-i5x26ORXurt_pu8x1sgLAyVIItbuRThiux4wBg3Ls,7768
11
11
  pdd/code_generator.py,sha256=AxMRZKGIlLh9xWdn2FA6b3zSoZ-5TIZNIAzqjFboAQs,4718
12
- pdd/code_generator_main.py,sha256=WmPdOUqkOy-P3apUsyBeFvRkObgXEZnmUBxA9h9cgTc,27945
12
+ pdd/code_generator_main.py,sha256=RwyjzrC1NHOfJJkfxdwWwJf_UNAy2lCWjSyasucG2KU,27997
13
13
  pdd/comment_line.py,sha256=sX2hf4bG1fILi_rvI9MkkwCZ2IitgKkW7nOiw8aQKPY,1845
14
14
  pdd/conflicts_in_prompts.py,sha256=9N3rZWdJUGayOTOgnHW9G_Jm1C9G4Y8hSLhnURc1BkY,4890
15
- pdd/conflicts_main.py,sha256=U23aJqJ6pgLDDCz-AaejWnG-qsTGAhZ9024KsHR9pYU,3650
16
- pdd/construct_paths.py,sha256=RANlDYtLDp0YNqFPgpQBZvdp038wkkgvFkXGytWKyJw,33251
15
+ pdd/conflicts_main.py,sha256=SK8eljbAY_wWT4dieRSsQwBrU1Dm90MImry3AGL-Dj4,3704
16
+ pdd/construct_paths.py,sha256=BDXDazbMOwgSLbYhCmgUwYIg0QPrjj8AVRbmFGJQIm4,33966
17
17
  pdd/context_generator.py,sha256=HAptXNSFTGu4rHw2SceiCcoCunIemESNCMVNqY1w6hU,6107
18
- pdd/context_generator_main.py,sha256=3riIDV2QskAMP-eq-uFicML79zQ5X-KMdw91g1RbP4E,4094
18
+ pdd/context_generator_main.py,sha256=ORpokRM9ZToBdMhFpM76iXkCGySyv2wsbQiyl4Ir5lQ,4147
19
19
  pdd/continue_generation.py,sha256=nEkAKZd9lM7OelQkffP99Y-JLxTFZeY3AH9VLRQCjHg,7854
20
- pdd/crash_main.py,sha256=BmTbFSrEAICS-Ji7sTFI9SHpTTUZot16918wiypNnhc,7611
20
+ pdd/crash_main.py,sha256=ICiMbpCxdu6bjtLssKgTlVQK3PXXXjFRAX9CL0VJuH8,7665
21
21
  pdd/detect_change.py,sha256=mA6k62xqeU1UG__CjzveJK0JDiRAO7AAC-JUfS0i2HQ,5510
22
- pdd/detect_change_main.py,sha256=J8YBJiWZNrE1ceCkS8CFtShTgaScJE9oYO0m_OXbXV0,3809
22
+ pdd/detect_change_main.py,sha256=aEehiFlKAfqegW6e18gVMKxbcSQpV9gqLpyX7Bl7Chw,3863
23
23
  pdd/edit_file.py,sha256=-FhZ-KGKYkPbnt0zFiDnnosPLh3bbKmften0Ios4-90,35017
24
24
  pdd/find_section.py,sha256=lz_FPY4KDCRAGlL1pWVZiutUNv7E4KsDFK-ymDWA_Ec,962
25
25
  pdd/fix_code_loop.py,sha256=LQXYQuFMjMM4yo6oJaFKyCg9OHpFwATp6QeHm8TsGR4,24468
26
26
  pdd/fix_code_module_errors.py,sha256=jKH88KunVhof1MYRI_F42_YnLt5k4lif4YztQgzB9g8,5446
27
27
  pdd/fix_error_loop.py,sha256=lhJrfJuFi_dB7hWTbpJfLEEZaltaRXYDl0XScDLvbdk,26464
28
28
  pdd/fix_errors_from_unit_tests.py,sha256=fIqEfVIEx8PPSAzWu5nhin_remKu4c0_o51AN3g_x6s,9398
29
- pdd/fix_main.py,sha256=7TbHVUM2HuzCVMY-B2iHzvy5YEnKaaSbU1ZzXN7YG3U,14004
29
+ pdd/fix_main.py,sha256=F0A9nv0ayYAqTMthluAzw2gvuFwEcZpec_0v8Krfd0s,14058
30
30
  pdd/fix_verification_errors.py,sha256=HvqGGdQqHq7OERmzcYP8Ft5nX_xthwVPJPG-YLv6VNM,17444
31
31
  pdd/fix_verification_errors_loop.py,sha256=80899aKg27wM9-I5wOoiHbbla5Bfm0bOibx7WNmiWPE,55715
32
- pdd/fix_verification_main.py,sha256=nZP0uYx9WLULSl17Du9mgENNO7UWgXFXJWKxIJy0e3Q,24237
32
+ pdd/fix_verification_main.py,sha256=lnhe4Sr6eV8EZEOTsSrzgxB_Ili5OJ0ZeFij_4Coc-E,24289
33
33
  pdd/generate_output_paths.py,sha256=YYxeEKiHf39s-giDu4ak_xufyfRqkuCcvowVuOytXaI,24224
34
34
  pdd/generate_test.py,sha256=Kd-iZnbHhGsgY6aD7Nu3i10ZNDpu3CVQROwAOYcjBok,6993
35
35
  pdd/get_comment.py,sha256=yuRtk68-SDkMaGzOSyIFdldRoymJBRSKjOYkr0narVc,2627
@@ -51,26 +51,26 @@ pdd/pdd_completion.zsh,sha256=f4BxXrLZUEcFeIUmXWdnFOTnTpJBFZ8KGpnIdjDdKFo,15353
51
51
  pdd/postprocess.py,sha256=mNw3iSDxE-eTYo3QwJCj_EmdEnnB5ysUN62YPapC_IM,4433
52
52
  pdd/postprocess_0.py,sha256=OW17GyCFLYErCyWh2tL4syuho3q2yFf2wyekQ4BLdPM,2168
53
53
  pdd/preprocess.py,sha256=XdMSJDqkMQk_wO7ysOYELIpIXEIig-9pBqiEhm9QdsU,10108
54
- pdd/preprocess_main.py,sha256=CwmU3WcXdsZ3vJN0Z0eCv_CbiybXu4O9BxFkCmZz6v4,3209
54
+ pdd/preprocess_main.py,sha256=WGhOB9qEu7MmFoyXNml_AmqGii73LJWngx4kTlZ526k,3262
55
55
  pdd/process_csv_change.py,sha256=ckNqVPRooWVyIvmqjdEgo2PDLnpoQ6Taa2dUaWGRlzU,27926
56
56
  pdd/pytest_output.py,sha256=IrRKYneW_F6zv9WaJwKFGnOBLFBFjk1CnhO_EVAjb9E,6612
57
57
  pdd/python_env_detector.py,sha256=y-QESoPNiKaD821uz8okX-9qA-oqvH9cQHY2_MwFHzU,5194
58
58
  pdd/split.py,sha256=9lWrh-JOjOpxRp4-s1VL7bqJMVWlsmY5LxONT7sYM8A,5288
59
- pdd/split_main.py,sha256=GJzkWvDB6AA_duT2nZTRIvPmrX-ePhDRpZuog5xFCT0,4791
59
+ pdd/split_main.py,sha256=52rcZoeS_wpYRiqbqMUgr_hUY7GS62otwzDfuAGi6YA,4845
60
60
  pdd/summarize_directory.py,sha256=BR3-yGcmUdDT26vWLGokBo6mAZzaT7PzoY_qZriH3cc,10061
61
61
  pdd/sync_animation.py,sha256=e7Qb4m70BHYpl37CuuF-95j-APctPL4Zm_o1PSTTRFQ,28070
62
- pdd/sync_determine_operation.py,sha256=16Co4_IE0AZBLPdICi2MqW3730hiyLdqOf2kZcQA2cc,59590
63
- pdd/sync_main.py,sha256=2XUZZL9oIiNVsVohdsMpvrNoV8XkXhEKyt5bb2HlNHI,13641
64
- pdd/sync_orchestration.py,sha256=W23k6-acwkWvd6UNtsrpFbgx_SW5HwlDbFhIHd1AL30,69869
62
+ pdd/sync_determine_operation.py,sha256=o4wQSaOP3rGzkPuB5aVySdzhYdHiMWQvXFZPHZl99pc,60248
63
+ pdd/sync_main.py,sha256=MrQldtBDeClNPtBECRR4Sy5LM_-TkPSNSnuNXdTxb10,13744
64
+ pdd/sync_orchestration.py,sha256=tQydUxozSikHbXWBb8GtZMEDR3aRwePKdEGZukuH6uM,69966
65
65
  pdd/trace.py,sha256=Ty-r3ZQC5k3PUCUacgfzg4sO8RgcH8kquSDau-jHkec,10874
66
- pdd/trace_main.py,sha256=5gVmk60NY67eCynWGM_qG81iLZj4G9epneNgqUGw_GU,4939
66
+ pdd/trace_main.py,sha256=SOnMEHta9WaMAxulMrk6aFojma4ti61ILvJp3NVhpbg,4992
67
67
  pdd/track_cost.py,sha256=vsLrQmipjG1BW4P9Wl33qoS8XFJDYBVY4ruQqKjPEx0,4238
68
68
  pdd/unfinished_prompt.py,sha256=8En5NZqg6eCL6b451T_ndJx5ln1XDtFJyieW4pKRakE,5955
69
- pdd/update_main.py,sha256=okTsl-oamzCOqjpircs58urBt4Cu7PXxOztvc57088Q,4332
69
+ pdd/update_main.py,sha256=SWCd7Us3YatrDR7B66dQCpRCIgQoMHysPzxa4dedVmk,4385
70
70
  pdd/update_model_costs.py,sha256=RfeOlAHtc1FCx47A7CjrH2t5WXQclQ_9uYtNjtQh75I,22998
71
71
  pdd/update_prompt.py,sha256=zc-HiI1cwGBkJHVmNDyoSZa13lZH90VdB9l8ajdj6Kk,4543
72
72
  pdd/xml_tagger.py,sha256=5Bc3HRm7iz_XjBdzQIcMb8KocUQ8PELI2NN5Gw4amd4,4825
73
- pdd/data/language_format.csv,sha256=yQW5PuqIpihhDF9r_4o5x1CNUU5yyx-mdhbS6GQaEEI,918
73
+ pdd/data/language_format.csv,sha256=pWF3yCh6xOFNmrr2TxTnye7EPKT3c-LPjmYV3Qc0a-Y,933
74
74
  pdd/data/llm_model.csv,sha256=UxllgS0btSpCKpPgPnaTFAtZsAynBhLeZyoIVo0Tpwc,1698
75
75
  pdd/prompts/auto_include_LLM.prompt,sha256=sNF2rdJu9wJ8c0lwjCfZ9ZReX8zGXRUNehRs1ZiyDoc,12108
76
76
  pdd/prompts/bug_to_unit_test_LLM.prompt,sha256=KdMkvRVnjVSf0NTYIaDXIMT93xPttXEwkMpjWx5leLs,1588
@@ -108,9 +108,9 @@ pdd/prompts/trim_results_start_LLM.prompt,sha256=OKz8fAf1cYWKWgslFOHEkUpfaUDARh3
108
108
  pdd/prompts/unfinished_prompt_LLM.prompt,sha256=vud_G9PlVv9Ig64uBC-hPEVFRk5lwpc8pW6tOIxJM4I,5082
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.55.dist-info/licenses/LICENSE,sha256=kvTJnnxPVTYlGKSY4ZN1kzdmJ0lxRdNWxgupaB27zsU,1066
112
- pdd_cli-0.0.55.dist-info/METADATA,sha256=rTxcHx_5zGrZE1Wmt70PckDsEHfo6GGtV_0id6UraZc,12597
113
- pdd_cli-0.0.55.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
114
- pdd_cli-0.0.55.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
115
- pdd_cli-0.0.55.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
116
- pdd_cli-0.0.55.dist-info/RECORD,,
111
+ pdd_cli-0.0.56.dist-info/licenses/LICENSE,sha256=kvTJnnxPVTYlGKSY4ZN1kzdmJ0lxRdNWxgupaB27zsU,1066
112
+ pdd_cli-0.0.56.dist-info/METADATA,sha256=xVQb-QcyhglRDa-RDyTZ4EuSvQccTUcdlfaL5L8PR9s,12597
113
+ pdd_cli-0.0.56.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
114
+ pdd_cli-0.0.56.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
115
+ pdd_cli-0.0.56.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
116
+ pdd_cli-0.0.56.dist-info/RECORD,,