pdd-cli 0.0.45__py3-none-any.whl → 0.0.90__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 (114) hide show
  1. pdd/__init__.py +4 -4
  2. pdd/agentic_common.py +863 -0
  3. pdd/agentic_crash.py +534 -0
  4. pdd/agentic_fix.py +1179 -0
  5. pdd/agentic_langtest.py +162 -0
  6. pdd/agentic_update.py +370 -0
  7. pdd/agentic_verify.py +183 -0
  8. pdd/auto_deps_main.py +15 -5
  9. pdd/auto_include.py +63 -5
  10. pdd/bug_main.py +3 -2
  11. pdd/bug_to_unit_test.py +2 -0
  12. pdd/change_main.py +11 -4
  13. pdd/cli.py +22 -1181
  14. pdd/cmd_test_main.py +73 -21
  15. pdd/code_generator.py +58 -18
  16. pdd/code_generator_main.py +672 -25
  17. pdd/commands/__init__.py +42 -0
  18. pdd/commands/analysis.py +248 -0
  19. pdd/commands/fix.py +140 -0
  20. pdd/commands/generate.py +257 -0
  21. pdd/commands/maintenance.py +174 -0
  22. pdd/commands/misc.py +79 -0
  23. pdd/commands/modify.py +230 -0
  24. pdd/commands/report.py +144 -0
  25. pdd/commands/templates.py +215 -0
  26. pdd/commands/utility.py +110 -0
  27. pdd/config_resolution.py +58 -0
  28. pdd/conflicts_main.py +8 -3
  29. pdd/construct_paths.py +258 -82
  30. pdd/context_generator.py +10 -2
  31. pdd/context_generator_main.py +113 -11
  32. pdd/continue_generation.py +47 -7
  33. pdd/core/__init__.py +0 -0
  34. pdd/core/cli.py +503 -0
  35. pdd/core/dump.py +554 -0
  36. pdd/core/errors.py +63 -0
  37. pdd/core/utils.py +90 -0
  38. pdd/crash_main.py +44 -11
  39. pdd/data/language_format.csv +71 -63
  40. pdd/data/llm_model.csv +20 -18
  41. pdd/detect_change_main.py +5 -4
  42. pdd/fix_code_loop.py +330 -76
  43. pdd/fix_error_loop.py +207 -61
  44. pdd/fix_errors_from_unit_tests.py +4 -3
  45. pdd/fix_main.py +75 -18
  46. pdd/fix_verification_errors.py +12 -100
  47. pdd/fix_verification_errors_loop.py +306 -272
  48. pdd/fix_verification_main.py +28 -9
  49. pdd/generate_output_paths.py +93 -10
  50. pdd/generate_test.py +16 -5
  51. pdd/get_jwt_token.py +9 -2
  52. pdd/get_run_command.py +73 -0
  53. pdd/get_test_command.py +68 -0
  54. pdd/git_update.py +70 -19
  55. pdd/incremental_code_generator.py +2 -2
  56. pdd/insert_includes.py +11 -3
  57. pdd/llm_invoke.py +1269 -103
  58. pdd/load_prompt_template.py +36 -10
  59. pdd/pdd_completion.fish +25 -2
  60. pdd/pdd_completion.sh +30 -4
  61. pdd/pdd_completion.zsh +79 -4
  62. pdd/postprocess.py +10 -3
  63. pdd/preprocess.py +228 -15
  64. pdd/preprocess_main.py +8 -5
  65. pdd/prompts/agentic_crash_explore_LLM.prompt +49 -0
  66. pdd/prompts/agentic_fix_explore_LLM.prompt +45 -0
  67. pdd/prompts/agentic_fix_harvest_only_LLM.prompt +48 -0
  68. pdd/prompts/agentic_fix_primary_LLM.prompt +85 -0
  69. pdd/prompts/agentic_update_LLM.prompt +1071 -0
  70. pdd/prompts/agentic_verify_explore_LLM.prompt +45 -0
  71. pdd/prompts/auto_include_LLM.prompt +100 -905
  72. pdd/prompts/detect_change_LLM.prompt +122 -20
  73. pdd/prompts/example_generator_LLM.prompt +22 -1
  74. pdd/prompts/extract_code_LLM.prompt +5 -1
  75. pdd/prompts/extract_program_code_fix_LLM.prompt +7 -1
  76. pdd/prompts/extract_prompt_update_LLM.prompt +7 -8
  77. pdd/prompts/extract_promptline_LLM.prompt +17 -11
  78. pdd/prompts/find_verification_errors_LLM.prompt +6 -0
  79. pdd/prompts/fix_code_module_errors_LLM.prompt +4 -2
  80. pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +8 -0
  81. pdd/prompts/fix_verification_errors_LLM.prompt +22 -0
  82. pdd/prompts/generate_test_LLM.prompt +21 -6
  83. pdd/prompts/increase_tests_LLM.prompt +1 -5
  84. pdd/prompts/insert_includes_LLM.prompt +228 -108
  85. pdd/prompts/trace_LLM.prompt +25 -22
  86. pdd/prompts/unfinished_prompt_LLM.prompt +85 -1
  87. pdd/prompts/update_prompt_LLM.prompt +22 -1
  88. pdd/pytest_output.py +127 -12
  89. pdd/render_mermaid.py +236 -0
  90. pdd/setup_tool.py +648 -0
  91. pdd/simple_math.py +2 -0
  92. pdd/split_main.py +3 -2
  93. pdd/summarize_directory.py +49 -6
  94. pdd/sync_determine_operation.py +543 -98
  95. pdd/sync_main.py +81 -31
  96. pdd/sync_orchestration.py +1334 -751
  97. pdd/sync_tui.py +848 -0
  98. pdd/template_registry.py +264 -0
  99. pdd/templates/architecture/architecture_json.prompt +242 -0
  100. pdd/templates/generic/generate_prompt.prompt +174 -0
  101. pdd/trace.py +168 -12
  102. pdd/trace_main.py +4 -3
  103. pdd/track_cost.py +151 -61
  104. pdd/unfinished_prompt.py +49 -3
  105. pdd/update_main.py +549 -67
  106. pdd/update_model_costs.py +2 -2
  107. pdd/update_prompt.py +19 -4
  108. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/METADATA +19 -6
  109. pdd_cli-0.0.90.dist-info/RECORD +153 -0
  110. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/licenses/LICENSE +1 -1
  111. pdd_cli-0.0.45.dist-info/RECORD +0 -116
  112. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/WHEEL +0 -0
  113. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/entry_points.txt +0 -0
  114. {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/top_level.txt +0 -0
@@ -23,18 +23,44 @@ def load_prompt_template(prompt_name: str) -> Optional[str]:
23
23
  print_formatted("[red]Unexpected error loading prompt template[/red]")
24
24
  return None
25
25
 
26
- # Step 1: Get project path from environment variable
27
- project_path = os.getenv('PDD_PATH')
28
- if not project_path:
29
- print_formatted("[red]PDD_PATH environment variable is not set[/red]")
30
- return None
26
+ # Step 1: Get project path from environment variable (preferred),
27
+ # else fall back to auto-detect based on this module's location or CWD.
28
+ project_path_env = os.getenv('PDD_PATH')
29
+ candidate_paths = []
30
+ if project_path_env:
31
+ candidate_paths.append(Path(project_path_env))
32
+
33
+ # Fallback 1: repository root inferred from this module (pdd/ => repo root)
34
+ try:
35
+ module_root = Path(__file__).resolve().parent # pdd/
36
+ repo_root = module_root.parent # repo root
37
+ candidate_paths.append(repo_root)
38
+ except Exception:
39
+ pass
31
40
 
32
- # Construct the full path to the prompt file
33
- prompt_path = Path(project_path) / 'prompts' / f"{prompt_name}.prompt"
41
+ # Fallback 2: current working directory
42
+ candidate_paths.append(Path.cwd())
43
+
44
+ # Build candidate prompt paths to try in order
45
+ prompt_candidates = []
46
+ for cp in candidate_paths:
47
+ # Check both <path>/prompts/ and <path>/pdd/prompts/
48
+ # The latter handles installed package case where prompts are in pdd/prompts/
49
+ prompt_candidates.append(cp / 'prompts' / f"{prompt_name}.prompt")
50
+ prompt_candidates.append(cp / 'pdd' / 'prompts' / f"{prompt_name}.prompt")
34
51
 
35
52
  # Step 2: Load and return the prompt template
36
- if not prompt_path.exists():
37
- print_formatted(f"[red]Prompt file not found: {prompt_path}[/red]")
53
+ prompt_path: Optional[Path] = None
54
+ for candidate in prompt_candidates:
55
+ if candidate.exists():
56
+ prompt_path = candidate
57
+ break
58
+
59
+ if prompt_path is None:
60
+ tried = "\n".join(str(c) for c in prompt_candidates)
61
+ print_formatted(
62
+ f"[red]Prompt file not found in any candidate locations for '{prompt_name}'. Tried:\n{tried}[/red]"
63
+ )
38
64
  return None
39
65
 
40
66
  try:
@@ -56,4 +82,4 @@ if __name__ == "__main__":
56
82
  prompt = load_prompt_template("example_prompt")
57
83
  if prompt:
58
84
  print_formatted("[blue]Loaded prompt template:[/blue]")
59
- print_formatted(prompt)
85
+ print_formatted(prompt)
pdd/pdd_completion.fish CHANGED
@@ -10,6 +10,8 @@ complete -c pdd -n "__fish_use_subcommand" -l quiet -d "Decrease output verbosit
10
10
  complete -c pdd -n "__fish_use_subcommand" -l output-cost -r -d "Enable cost tracking and output CSV file"
11
11
  complete -c pdd -n "__fish_use_subcommand" -l review-examples -d "Review few-shot examples before execution"
12
12
  complete -c pdd -n "__fish_use_subcommand" -l local -d "Run commands locally"
13
+ complete -c pdd -n "__fish_use_subcommand" -l context -r -d "Override .pddrc context"
14
+ complete -c pdd -n "__fish_use_subcommand" -l list-contexts -d ".pddrc contexts and exit"
13
15
  complete -c pdd -n "__fish_use_subcommand" -l help -d "Show help message"
14
16
  complete -c pdd -n "__fish_use_subcommand" -l version -d "Show version information"
15
17
 
@@ -27,13 +29,18 @@ complete -c pdd -n "__fish_use_subcommand" -a conflicts -d "Analyze conflicts be
27
29
  complete -c pdd -n "__fish_use_subcommand" -a crash -d "Fix code causing program crash"
28
30
  complete -c pdd -n "__fish_use_subcommand" -a trace -d "Trace code line to prompt"
29
31
  complete -c pdd -n "__fish_use_subcommand" -a bug -d "Generate unit test from bug report"
30
- complete -c pdd -n "__fish_use_subcommand" -a auto-deps -d "Analyze and insert dependencies"
32
+ complete -c pdd -n "__fish_use_subcommand" -a auto-deps -d "Analyze and insert dependencies from directory or glob"
31
33
  complete -c pdd -n "__fish_use_subcommand" -a verify -d "Verify functional correctness using LLM judgment"
34
+ complete -c pdd -n "__fish_use_subcommand" -a sync -d "Synchronize prompt, code, examples, tests"
35
+ complete -c pdd -n "__fish_use_subcommand" -a setup -d "Interactive setup and completion install"
36
+ complete -c pdd -n "__fish_use_subcommand" -a install_completion -d "Install shell completion"
37
+ complete -c pdd -n "__fish_use_subcommand" -a pytest-output -d "Run pytest and capture structured output"
32
38
 
33
39
  # Command-specific completions
34
40
  complete -c pdd -n "__fish_seen_subcommand_from generate" -l output -r -d "Output location for generated code"
35
41
  complete -c pdd -n "__fish_seen_subcommand_from generate" -l original-prompt -r -d "Original prompt file for incremental generation"
36
42
  complete -c pdd -n "__fish_seen_subcommand_from generate" -l incremental -d "Force incremental patching"
43
+ complete -c pdd -n "__fish_seen_subcommand_from generate" -s e -l env -xa "(env | cut -d= -f1 | sed 's/.*/&=/' | sort -u)" -d "Set template variable (KEY=VALUE) or read KEY from env"
37
44
  complete -c pdd -n "__fish_seen_subcommand_from generate" -a "(__fish_complete_suffix .prompt)"
38
45
 
39
46
  complete -c pdd -n "__fish_seen_subcommand_from example" -l output -r -d "Output location for example code"
@@ -125,10 +132,26 @@ complete -c pdd -n "__fish_seen_subcommand_from verify" -l budget -x -d "Max bud
125
132
  complete -c pdd -n "__fish_seen_subcommand_from verify" -a "(__fish_complete_suffix .prompt)"
126
133
  complete -c pdd -n "__fish_seen_subcommand_from verify" -a "(__fish_complete_suffix .py .js .java .cpp .rb .go)" # For CODE_FILE and PROGRAM_FILE
127
134
 
135
+ # sync command
136
+ complete -c pdd -n "__fish_seen_subcommand_from sync" -l max-attempts -x -d "Max attempts for loops"
137
+ complete -c pdd -n "__fish_seen_subcommand_from sync" -l budget -x -d "Total budget for sync"
138
+ complete -c pdd -n "__fish_seen_subcommand_from sync" -l skip-verify -d "Skip functional verification"
139
+ complete -c pdd -n "__fish_seen_subcommand_from sync" -l skip-tests -d "Skip unit test generation"
140
+ complete -c pdd -n "__fish_seen_subcommand_from sync" -l target-coverage -x -d "Desired coverage percentage"
141
+ complete -c pdd -n "__fish_seen_subcommand_from sync" -l log -d "Show analysis instead of running"
142
+
143
+ # setup and install_completion have no options
144
+ complete -c pdd -n "__fish_seen_subcommand_from setup" -d "Run interactive setup"
145
+ complete -c pdd -n "__fish_seen_subcommand_from install_completion" -d "Install shell completion"
146
+
147
+ # pytest-output command
148
+ complete -c pdd -n "__fish_seen_subcommand_from pytest-output" -l json-only -d "Print only JSON"
149
+ complete -c pdd -n "__fish_seen_subcommand_from pytest-output" -a "(__fish_complete_suffix .py)"
150
+
128
151
  # File completion for all commands
129
152
  complete -c pdd -n "__fish_seen_subcommand_from generate example test preprocess fix split change update detect conflicts crash trace bug auto-deps verify" -a "(__fish_complete_suffix .prompt)"
130
153
  complete -c pdd -n "__fish_seen_subcommand_from generate example test preprocess fix split change update detect conflicts crash trace bug auto-deps verify" -a "(__fish_complete_suffix .py .js .java .cpp .rb .go)"
131
154
  complete -c pdd -n "__fish_seen_subcommand_from generate example test preprocess fix split change update detect conflicts crash trace bug auto-deps verify" -a "(__fish_complete_suffix .log .txt .csv)"
132
155
 
133
156
  # Help completion
134
- complete -c pdd -n "__fish_seen_subcommand_from help" -a "generate example test preprocess fix split change update detect conflicts crash trace bug auto-deps verify" -d "Show help for specific command"
157
+ complete -c pdd -n "__fish_seen_subcommand_from help" -a "generate example test preprocess fix split change update detect conflicts crash trace bug auto-deps verify sync setup install_completion pytest-output" -d "Show help for specific command"
pdd/pdd_completion.sh CHANGED
@@ -15,13 +15,13 @@ _pdd() {
15
15
  cword=$COMP_CWORD
16
16
 
17
17
  # Global options
18
- local global_opts="--force --strength --time --temperature --verbose --quiet --output-cost --review-examples --local --help --version"
18
+ local global_opts="--force --strength --time --temperature --verbose --quiet --output-cost --review-examples --local --context --list-contexts --help --version"
19
19
 
20
20
  # Commands
21
- local commands="generate example test preprocess fix split change update detect conflicts crash trace bug auto-deps verify"
21
+ local commands="generate example test preprocess fix split change update detect conflicts crash trace bug auto-deps verify sync setup install_completion pytest-output"
22
22
 
23
23
  # Command-specific options
24
- local generate_opts="--output --original-prompt --incremental"
24
+ local generate_opts="--output --original-prompt --incremental --env -e"
25
25
  local example_opts="--output"
26
26
  local test_opts="--output --language --coverage-report --existing-tests --target-coverage --merge"
27
27
  local preprocess_opts="--output --xml --recursive --double --exclude"
@@ -36,6 +36,8 @@ _pdd() {
36
36
  local bug_opts="--output --language"
37
37
  local auto_deps_opts="--output --csv --force-scan"
38
38
  local verify_opts="--output-results --output-code --output-program --max-attempts --budget"
39
+ local sync_opts="--max-attempts --budget --skip-verify --skip-tests --target-coverage --log"
40
+ local pytest_output_opts="--json-only"
39
41
 
40
42
  # Complete global options before command
41
43
  if [[ $cword -eq 1 ]]; then
@@ -46,6 +48,16 @@ _pdd() {
46
48
  # Complete command-specific options
47
49
  case ${words[1]} in
48
50
  generate)
51
+ # If completing the value for -e/--env, suggest environment variable names (with and without '=')
52
+ if [[ $prev == "-e" || $prev == "--env" ]]; then
53
+ local vars
54
+ vars=$(env | cut -d= -f1 | sort -u)
55
+ # Offer both KEY and KEY=
56
+ local vars_with_eq
57
+ vars_with_eq=$(printf '%s=\n' $vars)
58
+ COMPREPLY=($(compgen -W "$vars $vars_with_eq" -- "$cur"))
59
+ return
60
+ fi
49
61
  _complete_files ".prompt"
50
62
  COMPREPLY+=($(compgen -W "$generate_opts" -- "$cur"))
51
63
  ;;
@@ -131,6 +143,20 @@ _pdd() {
131
143
  _complete_files
132
144
  COMPREPLY+=($(compgen -W "$verify_opts" -- "$cur"))
133
145
  ;;
146
+ sync)
147
+ # BASENAME (not a file), offer options
148
+ COMPREPLY+=($(compgen -W "$sync_opts" -- "$cur"))
149
+ ;;
150
+ setup)
151
+ # no command-specific options
152
+ ;;
153
+ install_completion)
154
+ # no command-specific options
155
+ ;;
156
+ pytest-output)
157
+ _complete_files
158
+ COMPREPLY+=($(compgen -W "$pytest_output_opts" -- "$cur"))
159
+ ;;
134
160
  *)
135
161
  COMPREPLY=($(compgen -W "$global_opts" -- "$cur"))
136
162
  ;;
@@ -157,4 +183,4 @@ _complete_files() {
157
183
  fi
158
184
  }
159
185
 
160
- complete -F _pdd pdd
186
+ complete -F _pdd pdd
pdd/pdd_completion.zsh CHANGED
@@ -57,6 +57,8 @@ _pdd_global_opts=(
57
57
  '--output-cost[Enable cost tracking and output a CSV file with usage details.]:filename:_files'
58
58
  '--review-examples[Review and optionally exclude few-shot examples before command execution.]'
59
59
  '--local[Run commands locally instead of in the cloud.]'
60
+ '--context[Override automatic .pddrc context]:context-name:_guard'
61
+ '--list-contexts[List available .pddrc contexts and exit]'
60
62
  '--help[Show help message and exit.]'
61
63
  '--version[Show version and exit.]'
62
64
  )
@@ -65,6 +67,14 @@ _pdd_global_opts=(
65
67
  # Per-subcommand completion functions
66
68
  ##
67
69
 
70
+ # Helper: suggest environment variables (KEY and KEY=)
71
+ _pdd_env_vars() {
72
+ local -a envs envs_eq
73
+ envs=(${(f)"$(env | cut -d= -f1 | sort -u)"})
74
+ envs_eq=(${envs/%/=})
75
+ _describe -t envvars 'environment variables' envs_eq envs
76
+ }
77
+
68
78
  # generate
69
79
  # Usage: pdd [GLOBAL OPTIONS] generate [OPTIONS] PROMPT_FILE
70
80
  # Options:
@@ -77,6 +87,7 @@ _pdd_generate() {
77
87
  '--output=[Specify where to save the generated code.]:filename:_files' \
78
88
  '--original-prompt=[The original prompt file used to generate existing code.]:filename:_files' \
79
89
  '--incremental[Force incremental patching even if changes are significant.]' \
90
+ '(-e --env)'{-e,--env}'[Set template variable (KEY=VALUE) or read KEY from env]:template variable:_pdd_env_vars' \
80
91
  '1:prompt-file:_files' \
81
92
  '*:filename:_files'
82
93
  }
@@ -349,7 +360,7 @@ _pdd_bug() {
349
360
  # --force-scan
350
361
  # Args:
351
362
  # 1: PROMPT_FILE
352
- # 2: DIRECTORY_PATH
363
+ # 2: DIRECTORY_PATH (directory or glob pattern)
353
364
  _pdd_auto_deps() {
354
365
  _arguments -s \
355
366
  $_pdd_global_opts \
@@ -357,7 +368,7 @@ _pdd_auto_deps() {
357
368
  '--csv=[CSV file for dependency info (default: project_dependencies.csv).]:filename:_files' \
358
369
  '--force-scan[Force rescanning of all potential dependency files.]' \
359
370
  '1:prompt-file:_files' \
360
- '2:directory:_files -/' \
371
+ '2:directory-or-glob:_files -/' \
361
372
  '*:filename:_files'
362
373
  }
363
374
 
@@ -387,6 +398,54 @@ _pdd_verify() {
387
398
  '*:filename:_files'
388
399
  }
389
400
 
401
+ # sync
402
+ # Usage: pdd [GLOBAL OPTIONS] sync [OPTIONS] BASENAME
403
+ # Options:
404
+ # --max-attempts [INT]
405
+ # --budget [FLOAT]
406
+ # --skip-verify
407
+ # --skip-tests
408
+ # --target-coverage [FLOAT]
409
+ # --log
410
+ # Arg:
411
+ # 1: BASENAME
412
+ _pdd_sync() {
413
+ _arguments -s \
414
+ $_pdd_global_opts \
415
+ '--max-attempts=[Maximum attempts for iterative loops (default 3)]:int' \
416
+ '--budget=[Maximum total cost for sync (default 10.0)]:float' \
417
+ '--skip-verify[Skip the functional verification step]' \
418
+ '--skip-tests[Skip unit test generation and fixing]' \
419
+ '--target-coverage=[Desired code coverage percentage]:float' \
420
+ '--log[Show analysis instead of executing operations]' \
421
+ '1:basename: ' \
422
+ '*: :'
423
+ }
424
+
425
+ # setup (no options)
426
+ _pdd_setup() {
427
+ _arguments -s $_pdd_global_opts
428
+ }
429
+
430
+ # install_completion (no options)
431
+ _pdd_install_completion() {
432
+ _arguments -s $_pdd_global_opts
433
+ }
434
+
435
+ # pytest-output
436
+ # Usage: pdd [GLOBAL OPTIONS] pytest-output [OPTIONS] TEST_FILE
437
+ # Options:
438
+ # --json-only
439
+ # Arg:
440
+ # 1: TEST_FILE
441
+ _pdd_pytest_output() {
442
+ _arguments -s \
443
+ $_pdd_global_opts \
444
+ '--json-only[Print only JSON to stdout]' \
445
+ '1:test-file:_files' \
446
+ '*:filename:_files'
447
+ }
448
+
390
449
  ##
391
450
  # Main PDD completion dispatcher
392
451
  ##
@@ -410,8 +469,12 @@ _pdd() {
410
469
  'crash:Fix errors in a code module and its calling program'
411
470
  'trace:Find the prompt file line number associated with a code line'
412
471
  'bug:Generate a unit test based on incorrect vs desired outputs'
413
- 'auto-deps:Analyze a prompt file and directory for needed dependencies'
472
+ 'auto-deps:Analyze a prompt and include deps from a directory or glob'
414
473
  'verify:Verify functional correctness using LLM judgment and iteratively fix'
474
+ 'sync:Synchronize prompt, code, examples, tests with analysis'
475
+ 'setup:Interactive setup and completion install'
476
+ 'install_completion:Install shell completion for current shell'
477
+ 'pytest-output:Run pytest and capture structured output'
415
478
  )
416
479
 
417
480
  # If there's no subcommand yet (i.e., user typed only "pdd " or "pdd -<Tab>"), offer global opts or subcommands.
@@ -471,6 +534,18 @@ _pdd() {
471
534
  verify)
472
535
  _pdd_verify
473
536
  ;;
537
+ sync)
538
+ _pdd_sync
539
+ ;;
540
+ setup)
541
+ _pdd_setup
542
+ ;;
543
+ install_completion)
544
+ _pdd_install_completion
545
+ ;;
546
+ pytest-output)
547
+ _pdd_pytest_output
548
+ ;;
474
549
  # If the subcommand is unknown or not typed yet, fall back to showing the list of subcommands.
475
550
  *)
476
551
  _describe -t subcommands 'pdd subcommand' _pdd_subcommands
@@ -487,4 +562,4 @@ else
487
562
  echo >&2 "Warning: Could not register pdd completion. Make sure ZSH completion system is working."
488
563
  fi
489
564
 
490
- # End of pdd_completion.zsh
565
+ # End of pdd_completion.zsh
pdd/postprocess.py CHANGED
@@ -3,7 +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
+ from . import DEFAULT_TIME, DEFAULT_STRENGTH
7
7
 
8
8
  class ExtractedCode(BaseModel):
9
9
  """Pydantic model for the extracted code."""
@@ -36,7 +36,7 @@ def postprocess_0(text: str) -> str:
36
36
  def postprocess(
37
37
  llm_output: str,
38
38
  language: str,
39
- strength: float = 0.9,
39
+ strength: float = DEFAULT_STRENGTH,
40
40
  temperature: float = 0,
41
41
  time: float = DEFAULT_TIME,
42
42
  verbose: bool = False
@@ -99,7 +99,14 @@ def postprocess(
99
99
  if not response or 'result' not in response:
100
100
  raise ValueError("Failed to get valid response from LLM")
101
101
 
102
- extracted_code_obj: ExtractedCode = response['result'] # Renamed for clarity
102
+ result_obj = response['result']
103
+ if not isinstance(result_obj, ExtractedCode):
104
+ # If we got a string (likely an error message from llm_invoke), fallback to simple extraction
105
+ if verbose:
106
+ print(f"[yellow]Structured extraction failed ({result_obj}). Falling back to simple extraction.[/yellow]")
107
+ return (postprocess_0(llm_output), response.get('cost', 0.0), response.get('model_name', 'fallback'))
108
+
109
+ extracted_code_obj: ExtractedCode = result_obj
103
110
  code_text = extracted_code_obj.extracted_code
104
111
 
105
112
  # Step 3c: Remove triple backticks and language identifier if present