pdd-cli 0.0.42__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.
- pdd/__init__.py +4 -4
- pdd/agentic_common.py +863 -0
- pdd/agentic_crash.py +534 -0
- pdd/agentic_fix.py +1179 -0
- pdd/agentic_langtest.py +162 -0
- pdd/agentic_update.py +370 -0
- pdd/agentic_verify.py +183 -0
- pdd/auto_deps_main.py +15 -5
- pdd/auto_include.py +63 -5
- pdd/bug_main.py +3 -2
- pdd/bug_to_unit_test.py +2 -0
- pdd/change_main.py +11 -4
- pdd/cli.py +22 -1181
- pdd/cmd_test_main.py +80 -19
- pdd/code_generator.py +58 -18
- pdd/code_generator_main.py +672 -25
- pdd/commands/__init__.py +42 -0
- pdd/commands/analysis.py +248 -0
- pdd/commands/fix.py +140 -0
- pdd/commands/generate.py +257 -0
- pdd/commands/maintenance.py +174 -0
- pdd/commands/misc.py +79 -0
- pdd/commands/modify.py +230 -0
- pdd/commands/report.py +144 -0
- pdd/commands/templates.py +215 -0
- pdd/commands/utility.py +110 -0
- pdd/config_resolution.py +58 -0
- pdd/conflicts_main.py +8 -3
- pdd/construct_paths.py +281 -81
- pdd/context_generator.py +10 -2
- pdd/context_generator_main.py +113 -11
- pdd/continue_generation.py +47 -7
- pdd/core/__init__.py +0 -0
- pdd/core/cli.py +503 -0
- pdd/core/dump.py +554 -0
- pdd/core/errors.py +63 -0
- pdd/core/utils.py +90 -0
- pdd/crash_main.py +44 -11
- pdd/data/language_format.csv +71 -62
- pdd/data/llm_model.csv +20 -18
- pdd/detect_change_main.py +5 -4
- pdd/fix_code_loop.py +331 -77
- pdd/fix_error_loop.py +209 -60
- pdd/fix_errors_from_unit_tests.py +4 -3
- pdd/fix_main.py +75 -18
- pdd/fix_verification_errors.py +12 -100
- pdd/fix_verification_errors_loop.py +319 -272
- pdd/fix_verification_main.py +57 -17
- pdd/generate_output_paths.py +93 -10
- pdd/generate_test.py +16 -5
- pdd/get_jwt_token.py +48 -9
- pdd/get_run_command.py +73 -0
- pdd/get_test_command.py +68 -0
- pdd/git_update.py +70 -19
- pdd/increase_tests.py +7 -0
- pdd/incremental_code_generator.py +2 -2
- pdd/insert_includes.py +11 -3
- pdd/llm_invoke.py +1278 -110
- pdd/load_prompt_template.py +36 -10
- pdd/pdd_completion.fish +25 -2
- pdd/pdd_completion.sh +30 -4
- pdd/pdd_completion.zsh +79 -4
- pdd/postprocess.py +10 -3
- pdd/preprocess.py +228 -15
- pdd/preprocess_main.py +8 -5
- pdd/prompts/agentic_crash_explore_LLM.prompt +49 -0
- pdd/prompts/agentic_fix_explore_LLM.prompt +45 -0
- pdd/prompts/agentic_fix_harvest_only_LLM.prompt +48 -0
- pdd/prompts/agentic_fix_primary_LLM.prompt +85 -0
- pdd/prompts/agentic_update_LLM.prompt +1071 -0
- pdd/prompts/agentic_verify_explore_LLM.prompt +45 -0
- pdd/prompts/auto_include_LLM.prompt +98 -101
- pdd/prompts/change_LLM.prompt +1 -3
- pdd/prompts/detect_change_LLM.prompt +562 -3
- pdd/prompts/example_generator_LLM.prompt +22 -1
- pdd/prompts/extract_code_LLM.prompt +5 -1
- pdd/prompts/extract_program_code_fix_LLM.prompt +14 -2
- pdd/prompts/extract_prompt_update_LLM.prompt +7 -8
- pdd/prompts/extract_promptline_LLM.prompt +17 -11
- pdd/prompts/find_verification_errors_LLM.prompt +6 -0
- pdd/prompts/fix_code_module_errors_LLM.prompt +16 -4
- pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +6 -41
- pdd/prompts/fix_verification_errors_LLM.prompt +22 -0
- pdd/prompts/generate_test_LLM.prompt +21 -6
- pdd/prompts/increase_tests_LLM.prompt +1 -2
- pdd/prompts/insert_includes_LLM.prompt +1181 -6
- pdd/prompts/split_LLM.prompt +1 -62
- pdd/prompts/trace_LLM.prompt +25 -22
- pdd/prompts/unfinished_prompt_LLM.prompt +85 -1
- pdd/prompts/update_prompt_LLM.prompt +22 -1
- pdd/prompts/xml_convertor_LLM.prompt +3246 -7
- pdd/pytest_output.py +188 -21
- pdd/python_env_detector.py +151 -0
- pdd/render_mermaid.py +236 -0
- pdd/setup_tool.py +648 -0
- pdd/simple_math.py +2 -0
- pdd/split_main.py +3 -2
- pdd/summarize_directory.py +56 -7
- pdd/sync_determine_operation.py +918 -186
- pdd/sync_main.py +82 -32
- pdd/sync_orchestration.py +1456 -453
- pdd/sync_tui.py +848 -0
- pdd/template_registry.py +264 -0
- pdd/templates/architecture/architecture_json.prompt +242 -0
- pdd/templates/generic/generate_prompt.prompt +174 -0
- pdd/trace.py +168 -12
- pdd/trace_main.py +4 -3
- pdd/track_cost.py +151 -61
- pdd/unfinished_prompt.py +49 -3
- pdd/update_main.py +549 -67
- pdd/update_model_costs.py +2 -2
- pdd/update_prompt.py +19 -4
- {pdd_cli-0.0.42.dist-info → pdd_cli-0.0.90.dist-info}/METADATA +20 -7
- pdd_cli-0.0.90.dist-info/RECORD +153 -0
- {pdd_cli-0.0.42.dist-info → pdd_cli-0.0.90.dist-info}/licenses/LICENSE +1 -1
- pdd_cli-0.0.42.dist-info/RECORD +0 -115
- {pdd_cli-0.0.42.dist-info → pdd_cli-0.0.90.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.42.dist-info → pdd_cli-0.0.90.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.42.dist-info → pdd_cli-0.0.90.dist-info}/top_level.txt +0 -0
pdd/agentic_verify.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import os
|
|
5
|
+
import re
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
|
|
11
|
+
from .agentic_common import run_agentic_task
|
|
12
|
+
from .load_prompt_template import load_prompt_template
|
|
13
|
+
|
|
14
|
+
console = Console()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _get_file_mtimes(root: Path) -> dict[Path, float]:
|
|
18
|
+
"""
|
|
19
|
+
Recursively scan the directory to record file modification times.
|
|
20
|
+
Excludes common ignored directories like .git, __pycache__, .venv, etc.
|
|
21
|
+
"""
|
|
22
|
+
mtimes = {}
|
|
23
|
+
ignore_dirs = {".git", "__pycache__", ".venv", "venv", "node_modules", ".idea", ".vscode"}
|
|
24
|
+
|
|
25
|
+
for path in root.rglob("*"):
|
|
26
|
+
# Skip ignored directories
|
|
27
|
+
if any(part in ignore_dirs for part in path.parts):
|
|
28
|
+
continue
|
|
29
|
+
|
|
30
|
+
if path.is_file():
|
|
31
|
+
try:
|
|
32
|
+
mtimes[path] = path.stat().st_mtime
|
|
33
|
+
except OSError:
|
|
34
|
+
# Handle cases where file might disappear or be inaccessible during scan
|
|
35
|
+
continue
|
|
36
|
+
return mtimes
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _extract_json_from_text(text: str) -> dict[str, Any] | None:
|
|
40
|
+
"""
|
|
41
|
+
Attempts to extract a JSON object from a string.
|
|
42
|
+
Handles Markdown code blocks and raw JSON.
|
|
43
|
+
"""
|
|
44
|
+
# Try to find JSON within markdown code blocks first
|
|
45
|
+
json_block_pattern = r"```(?:json)?\s*(\{.*?\})\s*```"
|
|
46
|
+
match = re.search(json_block_pattern, text, re.DOTALL)
|
|
47
|
+
|
|
48
|
+
if match:
|
|
49
|
+
json_str = match.group(1)
|
|
50
|
+
else:
|
|
51
|
+
# Try to find the first opening brace and last closing brace
|
|
52
|
+
start = text.find("{")
|
|
53
|
+
end = text.rfind("}")
|
|
54
|
+
if start != -1 and end != -1 and end > start:
|
|
55
|
+
json_str = text[start : end + 1]
|
|
56
|
+
else:
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
return json.loads(json_str)
|
|
61
|
+
except json.JSONDecodeError:
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def run_agentic_verify(
|
|
66
|
+
prompt_file: Path,
|
|
67
|
+
code_file: Path,
|
|
68
|
+
program_file: Path,
|
|
69
|
+
verification_log_file: Path,
|
|
70
|
+
*,
|
|
71
|
+
verbose: bool = False,
|
|
72
|
+
quiet: bool = False,
|
|
73
|
+
) -> tuple[bool, str, float, str, list[str]]:
|
|
74
|
+
"""
|
|
75
|
+
Runs an agentic verification fallback.
|
|
76
|
+
|
|
77
|
+
This function delegates the verification fix to a CLI agent (explore mode).
|
|
78
|
+
It records file changes, parses the agent's JSON output, and returns the results.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
prompt_file: Path to the prompt specification file.
|
|
82
|
+
code_file: Path to the generated code file.
|
|
83
|
+
program_file: Path to the program/driver file.
|
|
84
|
+
verification_log_file: Path to the log containing previous failures.
|
|
85
|
+
verbose: Enable verbose logging.
|
|
86
|
+
quiet: Suppress standard output.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Tuple containing:
|
|
90
|
+
- success (bool): Whether the agent claims success.
|
|
91
|
+
- message (str): The explanation or output message.
|
|
92
|
+
- cost (float): Estimated cost of the operation.
|
|
93
|
+
- model (str): The model/provider used.
|
|
94
|
+
- changed_files (list[str]): List of files modified during execution.
|
|
95
|
+
"""
|
|
96
|
+
project_root = Path.cwd()
|
|
97
|
+
|
|
98
|
+
if not quiet:
|
|
99
|
+
console.print(f"[bold blue]Starting Agentic Verify (Explore Mode)[/bold blue]")
|
|
100
|
+
console.print(f"Context: {project_root}")
|
|
101
|
+
|
|
102
|
+
# 1. Load Prompt Template
|
|
103
|
+
template_name = "agentic_verify_explore_LLM"
|
|
104
|
+
template = load_prompt_template(template_name)
|
|
105
|
+
|
|
106
|
+
if not template:
|
|
107
|
+
error_msg = f"Failed to load prompt template: {template_name}"
|
|
108
|
+
console.print(f"[bold red]{error_msg}[/bold red]")
|
|
109
|
+
return False, error_msg, 0.0, "unknown", []
|
|
110
|
+
|
|
111
|
+
# 2. Prepare Context
|
|
112
|
+
if verification_log_file.exists():
|
|
113
|
+
previous_attempts = verification_log_file.read_text(encoding="utf-8")
|
|
114
|
+
else:
|
|
115
|
+
previous_attempts = "No previous verification logs found."
|
|
116
|
+
|
|
117
|
+
# 3. Format Instruction
|
|
118
|
+
instruction = template.format(
|
|
119
|
+
prompt_path=prompt_file.resolve(),
|
|
120
|
+
code_path=code_file.resolve(),
|
|
121
|
+
program_path=program_file.resolve(),
|
|
122
|
+
project_root=project_root.resolve(),
|
|
123
|
+
previous_attempts=previous_attempts
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# 4. Record State Before Execution
|
|
127
|
+
mtimes_before = _get_file_mtimes(project_root)
|
|
128
|
+
|
|
129
|
+
# 5. Run Agentic Task
|
|
130
|
+
# We use the project root as the CWD so the agent can explore freely
|
|
131
|
+
agent_success, agent_output, cost, provider = run_agentic_task(
|
|
132
|
+
instruction=instruction,
|
|
133
|
+
cwd=project_root,
|
|
134
|
+
verbose=verbose,
|
|
135
|
+
quiet=quiet,
|
|
136
|
+
label="verify-explore"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# 6. Record State After Execution & Detect Changes
|
|
140
|
+
mtimes_after = _get_file_mtimes(project_root)
|
|
141
|
+
changed_files = []
|
|
142
|
+
|
|
143
|
+
for path, mtime in mtimes_after.items():
|
|
144
|
+
# Check if file is new or modified
|
|
145
|
+
if path not in mtimes_before or mtimes_before[path] != mtime:
|
|
146
|
+
# Store relative path for cleaner output
|
|
147
|
+
try:
|
|
148
|
+
rel_path = path.relative_to(project_root)
|
|
149
|
+
changed_files.append(str(rel_path))
|
|
150
|
+
except ValueError:
|
|
151
|
+
changed_files.append(str(path))
|
|
152
|
+
|
|
153
|
+
# 7. Parse Agent Output
|
|
154
|
+
# The agent is instructed to return JSON.
|
|
155
|
+
parsed_data = _extract_json_from_text(agent_output)
|
|
156
|
+
|
|
157
|
+
final_success = False
|
|
158
|
+
final_message = agent_output
|
|
159
|
+
|
|
160
|
+
if parsed_data:
|
|
161
|
+
# Trust the agent's self-reported success if JSON is valid
|
|
162
|
+
final_success = parsed_data.get("success", False)
|
|
163
|
+
final_message = parsed_data.get("message", agent_output)
|
|
164
|
+
|
|
165
|
+
# We prefer our calculated changed_files, but if we found none and the agent
|
|
166
|
+
# claims to have changed some (and they exist), we could log that discrepancy.
|
|
167
|
+
# For now, we stick to the physical reality of mtimes.
|
|
168
|
+
else:
|
|
169
|
+
# Fallback if agent didn't output valid JSON but the CLI tool reported success
|
|
170
|
+
if verbose:
|
|
171
|
+
console.print("[yellow]Warning: Could not parse JSON from agent output. Using raw output.[/yellow]")
|
|
172
|
+
|
|
173
|
+
# If the CLI tool failed (agent_success is False), we definitely failed.
|
|
174
|
+
# If the CLI tool succeeded, we still default to False because we couldn't verify the JSON contract.
|
|
175
|
+
final_success = False
|
|
176
|
+
|
|
177
|
+
if not quiet:
|
|
178
|
+
status_color = "green" if final_success else "red"
|
|
179
|
+
console.print(f"[{status_color}]Agentic Verify Finished. Success: {final_success}[/{status_color}]")
|
|
180
|
+
if changed_files:
|
|
181
|
+
console.print(f"Changed files: {', '.join(changed_files)}")
|
|
182
|
+
|
|
183
|
+
return final_success, final_message, cost, provider, changed_files
|
pdd/auto_deps_main.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Main function for the auto-deps command."""
|
|
2
2
|
import sys
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import Tuple, Optional
|
|
4
|
+
from typing import Callable, Tuple, Optional
|
|
5
5
|
import click
|
|
6
6
|
from rich import print as rprint
|
|
7
7
|
|
|
@@ -15,7 +15,8 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
15
15
|
directory_path: str,
|
|
16
16
|
auto_deps_csv_path: Optional[str],
|
|
17
17
|
output: Optional[str],
|
|
18
|
-
force_scan: Optional[bool]
|
|
18
|
+
force_scan: Optional[bool],
|
|
19
|
+
progress_callback: Optional[Callable[[int, int], None]] = None
|
|
19
20
|
) -> Tuple[str, float, str]:
|
|
20
21
|
"""
|
|
21
22
|
Main function to analyze and insert dependencies into a prompt file.
|
|
@@ -27,6 +28,7 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
27
28
|
auto_deps_csv_path: Path to CSV file containing auto-dependency information.
|
|
28
29
|
output: Optional path to save the modified prompt file.
|
|
29
30
|
force_scan: Flag to force rescan of directory by deleting CSV file.
|
|
31
|
+
progress_callback: Callback for progress updates (current, total) for each file.
|
|
30
32
|
|
|
31
33
|
Returns:
|
|
32
34
|
Tuple containing:
|
|
@@ -49,7 +51,9 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
49
51
|
force=ctx.obj.get('force', False),
|
|
50
52
|
quiet=ctx.obj.get('quiet', False),
|
|
51
53
|
command="auto-deps",
|
|
52
|
-
command_options=command_options
|
|
54
|
+
command_options=command_options,
|
|
55
|
+
context_override=ctx.obj.get('context'),
|
|
56
|
+
confirm_callback=ctx.obj.get('confirm_callback')
|
|
53
57
|
)
|
|
54
58
|
|
|
55
59
|
# Get the CSV file path
|
|
@@ -74,10 +78,12 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
74
78
|
input_prompt=input_strings["prompt_file"],
|
|
75
79
|
directory_path=directory_path,
|
|
76
80
|
csv_filename=csv_path,
|
|
81
|
+
prompt_filename=prompt_file,
|
|
77
82
|
strength=strength,
|
|
78
83
|
temperature=temperature,
|
|
79
84
|
time=time_budget,
|
|
80
|
-
verbose=not ctx.obj.get('quiet', False)
|
|
85
|
+
verbose=not ctx.obj.get('quiet', False),
|
|
86
|
+
progress_callback=progress_callback
|
|
81
87
|
)
|
|
82
88
|
|
|
83
89
|
# Save the modified prompt to the output file
|
|
@@ -98,7 +104,11 @@ def auto_deps_main( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
98
104
|
|
|
99
105
|
return modified_prompt, total_cost, model_name
|
|
100
106
|
|
|
107
|
+
except click.Abort:
|
|
108
|
+
# User cancelled - re-raise to stop the sync loop
|
|
109
|
+
raise
|
|
101
110
|
except Exception as exc:
|
|
102
111
|
if not ctx.obj.get('quiet', False):
|
|
103
112
|
rprint(f"[bold red]Error:[/bold red] {str(exc)}")
|
|
104
|
-
sys.exit(1)
|
|
113
|
+
# Return error result instead of sys.exit(1) to allow orchestrator to handle gracefully
|
|
114
|
+
return "", 0.0, f"Error: {exc}"
|
pdd/auto_include.py
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
This module provides the `auto_include` function to automatically find and
|
|
3
3
|
insert dependencies into a prompt.
|
|
4
4
|
"""
|
|
5
|
+
import re
|
|
5
6
|
from io import StringIO
|
|
6
|
-
from typing import Tuple, Optional
|
|
7
|
+
from typing import Callable, Tuple, Optional
|
|
7
8
|
|
|
8
9
|
import pandas as pd
|
|
9
10
|
from pydantic import BaseModel, Field
|
|
@@ -61,11 +62,17 @@ def _load_prompts() -> tuple[str, str]:
|
|
|
61
62
|
return auto_include_prompt, extract_prompt
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
def _summarize(
|
|
65
|
+
def _summarize(
|
|
66
|
+
directory_path: str,
|
|
67
|
+
csv_file: Optional[str],
|
|
68
|
+
llm_kwargs: dict,
|
|
69
|
+
progress_callback: Optional[Callable[[int, int], None]] = None
|
|
70
|
+
) -> tuple[str, float, str]:
|
|
65
71
|
"""Summarize the directory."""
|
|
66
72
|
return summarize_directory(
|
|
67
73
|
directory_path=directory_path,
|
|
68
74
|
csv_file=csv_file,
|
|
75
|
+
progress_callback=progress_callback,
|
|
69
76
|
**llm_kwargs
|
|
70
77
|
)
|
|
71
78
|
|
|
@@ -108,14 +115,57 @@ def _run_llm_and_extract(
|
|
|
108
115
|
return dependencies, total_cost, model_name
|
|
109
116
|
|
|
110
117
|
|
|
118
|
+
def _extract_module_name(prompt_filename: Optional[str]) -> Optional[str]:
|
|
119
|
+
"""Extract module name from prompt filename.
|
|
120
|
+
|
|
121
|
+
Handles various language suffixes:
|
|
122
|
+
- 'prompts/agentic_fix_python.prompt' -> 'agentic_fix'
|
|
123
|
+
- 'prompts/some_module_LLM.prompt' -> 'some_module'
|
|
124
|
+
- 'prompts/cli_bash.prompt' -> 'cli'
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
prompt_filename: The prompt filename to extract the module name from.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
The module name, or None if it cannot be extracted.
|
|
131
|
+
"""
|
|
132
|
+
if not prompt_filename:
|
|
133
|
+
return None
|
|
134
|
+
# Pattern: captures module name before the last underscore + language + .prompt
|
|
135
|
+
# e.g., "agentic_fix_python.prompt" captures "agentic_fix"
|
|
136
|
+
match = re.search(r'([^/]+)_[^_]+\.prompt$', prompt_filename)
|
|
137
|
+
if match:
|
|
138
|
+
return match.group(1)
|
|
139
|
+
return None
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _filter_self_references(dependencies: str, module_name: Optional[str]) -> str:
|
|
143
|
+
"""Remove includes that reference the module's own example file.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
dependencies: The dependencies string containing include tags.
|
|
147
|
+
module_name: The module name to filter out self-references for.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
The dependencies string with self-referential includes removed.
|
|
151
|
+
"""
|
|
152
|
+
if not module_name:
|
|
153
|
+
return dependencies
|
|
154
|
+
# Pattern matches: <...><include>context/{module_name}_example.py</include></...>
|
|
155
|
+
pattern = rf'<[^>]+><include>context/{re.escape(module_name)}_example\.py</include></[^>]+>\s*'
|
|
156
|
+
return re.sub(pattern, '', dependencies)
|
|
157
|
+
|
|
158
|
+
|
|
111
159
|
def auto_include(
|
|
112
160
|
input_prompt: str,
|
|
113
161
|
directory_path: str,
|
|
114
162
|
csv_file: Optional[str] = None,
|
|
163
|
+
prompt_filename: Optional[str] = None,
|
|
115
164
|
strength: float = DEFAULT_STRENGTH,
|
|
116
165
|
temperature: float = 0.0,
|
|
117
166
|
time: float = DEFAULT_TIME,
|
|
118
|
-
verbose: bool = False
|
|
167
|
+
verbose: bool = False,
|
|
168
|
+
progress_callback: Optional[Callable[[int, int], None]] = None
|
|
119
169
|
) -> Tuple[str, str, float, str]:
|
|
120
170
|
"""
|
|
121
171
|
Automatically find and insert proper dependencies into the prompt.
|
|
@@ -124,10 +174,14 @@ def auto_include(
|
|
|
124
174
|
input_prompt (str): The prompt requiring includes
|
|
125
175
|
directory_path (str): Directory path of dependencies
|
|
126
176
|
csv_file (Optional[str]): Contents of existing CSV file
|
|
177
|
+
prompt_filename (Optional[str]): The prompt filename being processed,
|
|
178
|
+
used to filter out self-referential example files
|
|
127
179
|
strength (float): Strength of LLM model (0-1)
|
|
128
180
|
temperature (float): Temperature of LLM model (0-1)
|
|
129
181
|
time (float): Time budget for LLM calls
|
|
130
182
|
verbose (bool): Whether to print detailed information
|
|
183
|
+
progress_callback (Optional[Callable[[int, int], None]]): Callback for progress updates.
|
|
184
|
+
Called with (current, total) for each file processed.
|
|
131
185
|
|
|
132
186
|
Returns:
|
|
133
187
|
Tuple[str, str, float, str]: (dependencies, csv_output, total_cost, model_name)
|
|
@@ -152,7 +206,7 @@ def auto_include(
|
|
|
152
206
|
console.print(Panel("Step 2: Running summarize_directory", style="blue"))
|
|
153
207
|
|
|
154
208
|
csv_output, summary_cost, summary_model = _summarize(
|
|
155
|
-
directory_path, csv_file, llm_kwargs
|
|
209
|
+
directory_path, csv_file, llm_kwargs, progress_callback
|
|
156
210
|
)
|
|
157
211
|
|
|
158
212
|
available_includes = _get_available_includes_from_csv(csv_output)
|
|
@@ -167,7 +221,11 @@ def auto_include(
|
|
|
167
221
|
available_includes=available_includes,
|
|
168
222
|
llm_kwargs=llm_kwargs,
|
|
169
223
|
)
|
|
170
|
-
|
|
224
|
+
|
|
225
|
+
# Filter out self-referential includes (module's own example file)
|
|
226
|
+
module_name = _extract_module_name(prompt_filename)
|
|
227
|
+
dependencies = _filter_self_references(dependencies, module_name)
|
|
228
|
+
|
|
171
229
|
total_cost = summary_cost + llm_cost
|
|
172
230
|
model_name = llm_model_name or summary_model
|
|
173
231
|
|
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/bug_to_unit_test.py
CHANGED
|
@@ -108,6 +108,7 @@ def bug_to_unit_test( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
108
108
|
strength=0.89,
|
|
109
109
|
temperature=temperature,
|
|
110
110
|
time=time,
|
|
111
|
+
language=language,
|
|
111
112
|
verbose=False,
|
|
112
113
|
)
|
|
113
114
|
|
|
@@ -121,6 +122,7 @@ def bug_to_unit_test( # pylint: disable=too-many-arguments, too-many-locals
|
|
|
121
122
|
strength=strength,
|
|
122
123
|
temperature=temperature,
|
|
123
124
|
time=time,
|
|
125
|
+
language=language,
|
|
124
126
|
verbose=True,
|
|
125
127
|
)
|
|
126
128
|
total_cost += continued_cost
|
pdd/change_main.py
CHANGED
|
@@ -17,11 +17,11 @@ from rich import print as rprint
|
|
|
17
17
|
from rich.panel import Panel
|
|
18
18
|
|
|
19
19
|
# Use relative imports for internal modules
|
|
20
|
+
from .config_resolution import resolve_effective_config
|
|
20
21
|
from .construct_paths import construct_paths
|
|
21
22
|
from .change import change as change_func
|
|
22
23
|
from .process_csv_change import process_csv_change
|
|
23
24
|
from .get_extension import get_extension
|
|
24
|
-
from . import DEFAULT_STRENGTH, DEFAULT_TIME
|
|
25
25
|
|
|
26
26
|
# Set up logging
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
@@ -72,9 +72,8 @@ def change_main(
|
|
|
72
72
|
# Retrieve global options from context
|
|
73
73
|
force: bool = ctx.obj.get("force", False)
|
|
74
74
|
quiet: bool = ctx.obj.get("quiet", False)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
time_budget: float = ctx.obj.get("time", DEFAULT_TIME)
|
|
75
|
+
# Note: strength/temperature/time will be resolved after construct_paths
|
|
76
|
+
# using resolve_effective_config for proper priority handling
|
|
78
77
|
# --- Get language and extension from context ---
|
|
79
78
|
# These are crucial for knowing the target code file types, especially in CSV mode
|
|
80
79
|
target_language: str = ctx.obj.get("language", "")
|
|
@@ -203,6 +202,7 @@ def change_main(
|
|
|
203
202
|
quiet=quiet,
|
|
204
203
|
command="change",
|
|
205
204
|
command_options=command_options,
|
|
205
|
+
context_override=ctx.obj.get('context')
|
|
206
206
|
)
|
|
207
207
|
logger.debug("construct_paths returned:")
|
|
208
208
|
logger.debug(" input_strings keys: %s", list(input_strings.keys()))
|
|
@@ -215,6 +215,13 @@ def change_main(
|
|
|
215
215
|
logger.error(msg, exc_info=True)
|
|
216
216
|
return msg, 0.0, ""
|
|
217
217
|
|
|
218
|
+
# Use centralized config resolution with proper priority:
|
|
219
|
+
# CLI > pddrc > defaults
|
|
220
|
+
effective_config = resolve_effective_config(ctx, resolved_config)
|
|
221
|
+
strength = effective_config["strength"]
|
|
222
|
+
temperature = effective_config["temperature"]
|
|
223
|
+
time_budget = effective_config["time"]
|
|
224
|
+
|
|
218
225
|
# --- 3. Perform Prompt Modification ---
|
|
219
226
|
if use_csv:
|
|
220
227
|
logger.info("Running in CSV mode.")
|