pdd-cli 0.0.90__py3-none-any.whl → 0.0.121__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 +38 -6
- pdd/agentic_bug.py +323 -0
- pdd/agentic_bug_orchestrator.py +506 -0
- pdd/agentic_change.py +231 -0
- pdd/agentic_change_orchestrator.py +537 -0
- pdd/agentic_common.py +533 -770
- pdd/agentic_crash.py +2 -1
- pdd/agentic_e2e_fix.py +319 -0
- pdd/agentic_e2e_fix_orchestrator.py +582 -0
- pdd/agentic_fix.py +118 -3
- pdd/agentic_update.py +27 -9
- pdd/agentic_verify.py +3 -2
- pdd/architecture_sync.py +565 -0
- pdd/auth_service.py +210 -0
- pdd/auto_deps_main.py +63 -53
- pdd/auto_include.py +236 -3
- pdd/auto_update.py +125 -47
- pdd/bug_main.py +195 -23
- pdd/cmd_test_main.py +345 -197
- pdd/code_generator.py +4 -2
- pdd/code_generator_main.py +118 -32
- pdd/commands/__init__.py +6 -0
- pdd/commands/analysis.py +113 -48
- pdd/commands/auth.py +309 -0
- pdd/commands/connect.py +358 -0
- pdd/commands/fix.py +155 -114
- pdd/commands/generate.py +5 -0
- pdd/commands/maintenance.py +3 -2
- pdd/commands/misc.py +8 -0
- pdd/commands/modify.py +225 -163
- pdd/commands/sessions.py +284 -0
- pdd/commands/utility.py +12 -7
- pdd/construct_paths.py +334 -32
- pdd/context_generator_main.py +167 -170
- pdd/continue_generation.py +6 -3
- pdd/core/__init__.py +33 -0
- pdd/core/cli.py +44 -7
- pdd/core/cloud.py +237 -0
- pdd/core/dump.py +68 -20
- pdd/core/errors.py +4 -0
- pdd/core/remote_session.py +61 -0
- pdd/crash_main.py +219 -23
- pdd/data/llm_model.csv +4 -4
- pdd/docs/prompting_guide.md +864 -0
- pdd/docs/whitepaper_with_benchmarks/data_and_functions/benchmark_analysis.py +495 -0
- pdd/docs/whitepaper_with_benchmarks/data_and_functions/creation_compare.py +528 -0
- pdd/fix_code_loop.py +208 -34
- pdd/fix_code_module_errors.py +6 -2
- pdd/fix_error_loop.py +291 -38
- pdd/fix_main.py +208 -6
- pdd/fix_verification_errors_loop.py +235 -26
- pdd/fix_verification_main.py +269 -83
- pdd/frontend/dist/assets/index-B5DZHykP.css +1 -0
- pdd/frontend/dist/assets/index-CUWd8al1.js +450 -0
- pdd/frontend/dist/index.html +376 -0
- pdd/frontend/dist/logo.svg +33 -0
- pdd/generate_output_paths.py +46 -5
- pdd/generate_test.py +212 -151
- pdd/get_comment.py +19 -44
- pdd/get_extension.py +8 -9
- pdd/get_jwt_token.py +309 -20
- pdd/get_language.py +8 -7
- pdd/get_run_command.py +7 -5
- pdd/insert_includes.py +2 -1
- pdd/llm_invoke.py +531 -97
- pdd/load_prompt_template.py +15 -34
- pdd/operation_log.py +342 -0
- pdd/path_resolution.py +140 -0
- pdd/postprocess.py +122 -97
- pdd/preprocess.py +68 -12
- pdd/preprocess_main.py +33 -1
- pdd/prompts/agentic_bug_step10_pr_LLM.prompt +182 -0
- pdd/prompts/agentic_bug_step1_duplicate_LLM.prompt +73 -0
- pdd/prompts/agentic_bug_step2_docs_LLM.prompt +129 -0
- pdd/prompts/agentic_bug_step3_triage_LLM.prompt +95 -0
- pdd/prompts/agentic_bug_step4_reproduce_LLM.prompt +97 -0
- pdd/prompts/agentic_bug_step5_root_cause_LLM.prompt +123 -0
- pdd/prompts/agentic_bug_step6_test_plan_LLM.prompt +107 -0
- pdd/prompts/agentic_bug_step7_generate_LLM.prompt +172 -0
- pdd/prompts/agentic_bug_step8_verify_LLM.prompt +119 -0
- pdd/prompts/agentic_bug_step9_e2e_test_LLM.prompt +289 -0
- pdd/prompts/agentic_change_step10_identify_issues_LLM.prompt +1006 -0
- pdd/prompts/agentic_change_step11_fix_issues_LLM.prompt +984 -0
- pdd/prompts/agentic_change_step12_create_pr_LLM.prompt +140 -0
- pdd/prompts/agentic_change_step1_duplicate_LLM.prompt +73 -0
- pdd/prompts/agentic_change_step2_docs_LLM.prompt +101 -0
- pdd/prompts/agentic_change_step3_research_LLM.prompt +126 -0
- pdd/prompts/agentic_change_step4_clarify_LLM.prompt +164 -0
- pdd/prompts/agentic_change_step5_docs_change_LLM.prompt +981 -0
- pdd/prompts/agentic_change_step6_devunits_LLM.prompt +1005 -0
- pdd/prompts/agentic_change_step7_architecture_LLM.prompt +1044 -0
- pdd/prompts/agentic_change_step8_analyze_LLM.prompt +1027 -0
- pdd/prompts/agentic_change_step9_implement_LLM.prompt +1077 -0
- pdd/prompts/agentic_e2e_fix_step1_unit_tests_LLM.prompt +90 -0
- pdd/prompts/agentic_e2e_fix_step2_e2e_tests_LLM.prompt +91 -0
- pdd/prompts/agentic_e2e_fix_step3_root_cause_LLM.prompt +89 -0
- pdd/prompts/agentic_e2e_fix_step4_fix_e2e_tests_LLM.prompt +96 -0
- pdd/prompts/agentic_e2e_fix_step5_identify_devunits_LLM.prompt +91 -0
- pdd/prompts/agentic_e2e_fix_step6_create_unit_tests_LLM.prompt +106 -0
- pdd/prompts/agentic_e2e_fix_step7_verify_tests_LLM.prompt +116 -0
- pdd/prompts/agentic_e2e_fix_step8_run_pdd_fix_LLM.prompt +120 -0
- pdd/prompts/agentic_e2e_fix_step9_verify_all_LLM.prompt +146 -0
- pdd/prompts/agentic_fix_primary_LLM.prompt +2 -2
- pdd/prompts/agentic_update_LLM.prompt +192 -338
- pdd/prompts/auto_include_LLM.prompt +22 -0
- pdd/prompts/change_LLM.prompt +3093 -1
- pdd/prompts/detect_change_LLM.prompt +571 -14
- pdd/prompts/fix_code_module_errors_LLM.prompt +8 -0
- pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +1 -0
- pdd/prompts/generate_test_LLM.prompt +19 -1
- pdd/prompts/generate_test_from_example_LLM.prompt +366 -0
- pdd/prompts/insert_includes_LLM.prompt +262 -252
- pdd/prompts/prompt_code_diff_LLM.prompt +123 -0
- pdd/prompts/prompt_diff_LLM.prompt +82 -0
- pdd/remote_session.py +876 -0
- pdd/server/__init__.py +52 -0
- pdd/server/app.py +335 -0
- pdd/server/click_executor.py +587 -0
- pdd/server/executor.py +338 -0
- pdd/server/jobs.py +661 -0
- pdd/server/models.py +241 -0
- pdd/server/routes/__init__.py +31 -0
- pdd/server/routes/architecture.py +451 -0
- pdd/server/routes/auth.py +364 -0
- pdd/server/routes/commands.py +929 -0
- pdd/server/routes/config.py +42 -0
- pdd/server/routes/files.py +603 -0
- pdd/server/routes/prompts.py +1347 -0
- pdd/server/routes/websocket.py +473 -0
- pdd/server/security.py +243 -0
- pdd/server/terminal_spawner.py +217 -0
- pdd/server/token_counter.py +222 -0
- pdd/summarize_directory.py +236 -237
- pdd/sync_animation.py +8 -4
- pdd/sync_determine_operation.py +329 -47
- pdd/sync_main.py +272 -28
- pdd/sync_orchestration.py +289 -211
- pdd/sync_order.py +304 -0
- pdd/template_expander.py +161 -0
- pdd/templates/architecture/architecture_json.prompt +41 -46
- pdd/trace.py +1 -1
- pdd/track_cost.py +0 -13
- pdd/unfinished_prompt.py +2 -1
- pdd/update_main.py +68 -26
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.121.dist-info}/METADATA +15 -10
- pdd_cli-0.0.121.dist-info/RECORD +229 -0
- pdd_cli-0.0.90.dist-info/RECORD +0 -153
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.121.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.121.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.121.dist-info}/licenses/LICENSE +0 -0
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.121.dist-info}/top_level.txt +0 -0
pdd/commands/modify.py
CHANGED
|
@@ -1,32 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import click
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
from typing import
|
|
5
|
+
from typing import Optional, Tuple, Any
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
from rich.console import Console
|
|
7
9
|
|
|
10
|
+
# Relative imports from parent package
|
|
8
11
|
from ..split_main import split_main
|
|
9
12
|
from ..change_main import change_main
|
|
13
|
+
from ..agentic_change import run_agentic_change
|
|
10
14
|
from ..update_main import update_main
|
|
11
15
|
from ..track_cost import track_cost
|
|
12
16
|
from ..core.errors import handle_error
|
|
17
|
+
from ..operation_log import log_operation
|
|
13
18
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@click.
|
|
17
|
-
@click.argument("
|
|
18
|
-
@click.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
help="Specify where to save the generated sub-prompt file (file or directory).",
|
|
23
|
-
)
|
|
24
|
-
@click.option(
|
|
25
|
-
"--output-modified",
|
|
26
|
-
type=click.Path(writable=True),
|
|
27
|
-
default=None,
|
|
28
|
-
help="Specify where to save the modified prompt file (file or directory).",
|
|
29
|
-
)
|
|
19
|
+
console = Console()
|
|
20
|
+
|
|
21
|
+
@click.command()
|
|
22
|
+
@click.argument("input_prompt", type=click.Path(exists=True))
|
|
23
|
+
@click.argument("input_code", type=click.Path(exists=True))
|
|
24
|
+
@click.argument("example_code", type=click.Path(exists=True))
|
|
25
|
+
@click.option("--output-sub", help="Optional path for saving the sub-prompt.")
|
|
26
|
+
@click.option("--output-modified", help="Optional path for saving the modified prompt.")
|
|
30
27
|
@click.pass_context
|
|
31
28
|
@track_cost
|
|
32
29
|
def split(
|
|
@@ -36,13 +33,15 @@ def split(
|
|
|
36
33
|
example_code: str,
|
|
37
34
|
output_sub: Optional[str],
|
|
38
35
|
output_modified: Optional[str],
|
|
39
|
-
) -> Optional[Tuple[
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
) -> Optional[Tuple[Any, float, str]]:
|
|
37
|
+
"""
|
|
38
|
+
Split large complex prompt files into smaller, more manageable prompt files.
|
|
39
|
+
"""
|
|
40
|
+
ctx.ensure_object(dict)
|
|
43
41
|
try:
|
|
42
|
+
# Call split_main with required arguments
|
|
44
43
|
result_data, total_cost, model_name = split_main(
|
|
45
|
-
ctx
|
|
44
|
+
ctx,
|
|
46
45
|
input_prompt_file=input_prompt,
|
|
47
46
|
input_code_file=input_code,
|
|
48
47
|
example_code_file=example_code,
|
|
@@ -50,181 +49,244 @@ def split(
|
|
|
50
49
|
output_modified=output_modified,
|
|
51
50
|
)
|
|
52
51
|
return result_data, total_cost, model_name
|
|
52
|
+
|
|
53
53
|
except click.Abort:
|
|
54
54
|
raise
|
|
55
55
|
except Exception as e:
|
|
56
|
-
handle_error(e,
|
|
56
|
+
handle_error(e, "split", ctx.obj.get("quiet", False))
|
|
57
57
|
return None
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
@click.command(
|
|
61
|
-
@click.argument("
|
|
62
|
-
@click.
|
|
63
|
-
@click.
|
|
64
|
-
@click.option(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
show_default=True,
|
|
69
|
-
help="Maximum cost allowed for the change process.",
|
|
70
|
-
)
|
|
71
|
-
@click.option(
|
|
72
|
-
"--output",
|
|
73
|
-
type=click.Path(writable=True),
|
|
74
|
-
default=None,
|
|
75
|
-
help="Specify where to save the modified prompt file (file or directory).",
|
|
76
|
-
)
|
|
77
|
-
@click.option(
|
|
78
|
-
"--csv",
|
|
79
|
-
"use_csv",
|
|
80
|
-
is_flag=True,
|
|
81
|
-
default=False,
|
|
82
|
-
help="Use a CSV file for batch change prompts.",
|
|
83
|
-
)
|
|
60
|
+
@click.command()
|
|
61
|
+
@click.argument("args", nargs=-1)
|
|
62
|
+
@click.option("--manual", is_flag=True, default=False, help="Use legacy manual mode.")
|
|
63
|
+
@click.option("--budget", type=float, default=5.0, help="Budget for the operation.")
|
|
64
|
+
@click.option("--output", help="Output path.")
|
|
65
|
+
@click.option("--csv", is_flag=True, help="Use CSV input for batch processing.")
|
|
66
|
+
@click.option("--timeout-adder", type=float, default=0.0, help="Additional seconds to add to each step's timeout (agentic mode only).")
|
|
67
|
+
@click.option("--no-github-state", is_flag=True, default=False, help="Disable GitHub state persistence (agentic mode only).")
|
|
84
68
|
@click.pass_context
|
|
85
69
|
@track_cost
|
|
86
70
|
def change(
|
|
87
71
|
ctx: click.Context,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
input_prompt_file: Optional[str],
|
|
91
|
-
output: Optional[str],
|
|
92
|
-
use_csv: bool,
|
|
72
|
+
args: Tuple[str, ...],
|
|
73
|
+
manual: bool,
|
|
93
74
|
budget: float,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
75
|
+
output: Optional[str],
|
|
76
|
+
csv: bool,
|
|
77
|
+
timeout_adder: float,
|
|
78
|
+
no_github_state: bool,
|
|
79
|
+
) -> Optional[Tuple[Any, float, str]]:
|
|
80
|
+
"""
|
|
81
|
+
Modify an input prompt file based on a change prompt or issue.
|
|
82
|
+
|
|
83
|
+
Agentic Mode (default):
|
|
84
|
+
pdd change ISSUE_URL
|
|
85
|
+
|
|
86
|
+
Manual Mode (--manual):
|
|
87
|
+
pdd change --manual CHANGE_PROMPT_FILE INPUT_CODE_FILE [INPUT_PROMPT_FILE]
|
|
88
|
+
"""
|
|
89
|
+
ctx.ensure_object(dict)
|
|
90
|
+
|
|
98
91
|
try:
|
|
99
|
-
#
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
92
|
+
# Set budget in context for manual mode usage
|
|
93
|
+
ctx.obj["budget"] = budget
|
|
94
|
+
|
|
95
|
+
quiet = ctx.obj.get("quiet", False)
|
|
96
|
+
verbose = ctx.obj.get("verbose", False)
|
|
97
|
+
|
|
98
|
+
if manual:
|
|
99
|
+
# Manual Mode Validation and Execution
|
|
100
|
+
if csv:
|
|
101
|
+
# CSV Mode: Expecting CSV_FILE and CODE_DIRECTORY (no input_prompt)
|
|
102
|
+
if len(args) == 3:
|
|
103
|
+
raise click.UsageError("Cannot use --csv and specify an INPUT_PROMPT_FILE simultaneously.")
|
|
104
|
+
if len(args) != 2:
|
|
105
|
+
raise click.UsageError("CSV mode requires 2 arguments: CSV_FILE CODE_DIRECTORY")
|
|
106
|
+
|
|
107
|
+
change_file, input_code = args
|
|
108
|
+
input_prompt = None
|
|
109
|
+
|
|
110
|
+
# CSV mode requires input_code to be a directory
|
|
111
|
+
if not Path(input_code).is_dir():
|
|
112
|
+
raise click.UsageError("INPUT_CODE must be a directory when using --csv")
|
|
113
|
+
else:
|
|
114
|
+
# Standard Manual Mode: Expecting 2 or 3 arguments
|
|
115
|
+
if len(args) == 3:
|
|
116
|
+
change_file, input_code, input_prompt = args
|
|
117
|
+
# Non-CSV mode requires input_code to be a file, not a directory
|
|
118
|
+
if Path(input_code).is_dir():
|
|
119
|
+
raise click.UsageError("INPUT_CODE must be a file when not using --csv")
|
|
120
|
+
elif len(args) == 2:
|
|
121
|
+
change_file, input_code = args
|
|
122
|
+
input_prompt = None
|
|
123
|
+
# Without CSV mode, input_prompt_file is required
|
|
124
|
+
raise click.UsageError("INPUT_PROMPT_FILE is required when not using --csv")
|
|
125
|
+
else:
|
|
126
|
+
raise click.UsageError(
|
|
127
|
+
"Manual mode requires 3 arguments: CHANGE_PROMPT INPUT_CODE INPUT_PROMPT"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Validate file existence
|
|
131
|
+
if not Path(change_file).exists():
|
|
132
|
+
raise click.UsageError(f"Change file not found: {change_file}")
|
|
133
|
+
if not Path(input_code).exists():
|
|
134
|
+
raise click.UsageError(f"Input code path not found: {input_code}")
|
|
135
|
+
if input_prompt and not Path(input_prompt).exists():
|
|
136
|
+
raise click.UsageError(f"Input prompt file not found: {input_prompt}")
|
|
137
|
+
|
|
138
|
+
# Call change_main
|
|
139
|
+
result, cost, model = change_main(
|
|
140
|
+
ctx=ctx,
|
|
141
|
+
change_prompt_file=change_file,
|
|
142
|
+
input_code=input_code,
|
|
143
|
+
input_prompt_file=input_prompt,
|
|
144
|
+
output=output,
|
|
145
|
+
use_csv=csv,
|
|
146
|
+
budget=budget
|
|
147
|
+
)
|
|
148
|
+
return result, cost, model
|
|
149
|
+
|
|
150
|
+
else:
|
|
151
|
+
# Agentic Mode Validation and Execution
|
|
152
|
+
if len(args) != 1:
|
|
153
|
+
raise click.UsageError("Agentic mode requires exactly 1 argument: ISSUE_URL")
|
|
154
|
+
|
|
155
|
+
issue_url = args[0]
|
|
156
|
+
|
|
157
|
+
# Call run_agentic_change
|
|
158
|
+
success, message, cost, model, changed_files = run_agentic_change(
|
|
159
|
+
issue_url=issue_url,
|
|
160
|
+
verbose=verbose,
|
|
161
|
+
quiet=quiet,
|
|
162
|
+
timeout_adder=timeout_adder,
|
|
163
|
+
use_github_state=not no_github_state
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
# Display results using click.echo as requested
|
|
167
|
+
if not quiet:
|
|
168
|
+
status = "Success" if success else "Failed"
|
|
169
|
+
click.echo(f"Status: {status}")
|
|
170
|
+
click.echo(f"Message: {message}")
|
|
171
|
+
click.echo(f"Cost: ${cost:.4f}")
|
|
172
|
+
click.echo(f"Model: {model}")
|
|
173
|
+
if changed_files:
|
|
174
|
+
click.echo("Changed files:")
|
|
175
|
+
for f in changed_files:
|
|
176
|
+
click.echo(f" - {f}")
|
|
177
|
+
|
|
178
|
+
return message, cost, model
|
|
179
|
+
|
|
125
180
|
except click.Abort:
|
|
126
181
|
raise
|
|
127
|
-
except
|
|
128
|
-
handle_error(e,
|
|
182
|
+
except Exception as e:
|
|
183
|
+
handle_error(e, "change", ctx.obj.get("quiet", False))
|
|
129
184
|
return None
|
|
130
185
|
|
|
131
186
|
|
|
132
|
-
@click.command(
|
|
133
|
-
@click.argument("
|
|
134
|
-
@click.
|
|
135
|
-
@click.
|
|
136
|
-
@click.option(
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
default=None,
|
|
140
|
-
help="Specify where to save the updated prompt file(s). For single files: saves to this specific path or directory. For repository mode: saves all prompts to this directory. If not specified, uses the original prompt location (single file) or 'prompts' directory (repository mode).",
|
|
141
|
-
)
|
|
142
|
-
@click.option(
|
|
143
|
-
"--git",
|
|
144
|
-
"use_git",
|
|
145
|
-
is_flag=True,
|
|
146
|
-
default=False,
|
|
147
|
-
help="Use git history to find the original code file.",
|
|
148
|
-
)
|
|
149
|
-
@click.option(
|
|
150
|
-
"--extensions",
|
|
151
|
-
type=str,
|
|
152
|
-
default=None,
|
|
153
|
-
help="Comma-separated list of file extensions to update in repo mode (e.g., 'py,js,ts').",
|
|
154
|
-
)
|
|
155
|
-
@click.option(
|
|
156
|
-
"--simple",
|
|
157
|
-
is_flag=True,
|
|
158
|
-
default=False,
|
|
159
|
-
help="Use legacy 2-stage LLM update instead of agentic mode.",
|
|
160
|
-
)
|
|
187
|
+
@click.command()
|
|
188
|
+
@click.argument("files", nargs=-1)
|
|
189
|
+
@click.option("--extensions", help="Comma-separated extensions for repo mode.")
|
|
190
|
+
@click.option("--directory", help="Directory to scan for repo mode.")
|
|
191
|
+
@click.option("--git", is_flag=True, help="Use git history for original code.")
|
|
192
|
+
@click.option("--output", help="Output path for the updated prompt.")
|
|
193
|
+
@click.option("--simple", is_flag=True, default=False, help="Use legacy simple update.")
|
|
161
194
|
@click.pass_context
|
|
195
|
+
@log_operation(operation="update", clears_run_report=True)
|
|
162
196
|
@track_cost
|
|
163
197
|
def update(
|
|
164
198
|
ctx: click.Context,
|
|
165
|
-
|
|
166
|
-
modified_code_file: Optional[str],
|
|
167
|
-
input_code_file: Optional[str],
|
|
168
|
-
output: Optional[str],
|
|
169
|
-
use_git: bool,
|
|
199
|
+
files: Tuple[str, ...],
|
|
170
200
|
extensions: Optional[str],
|
|
201
|
+
directory: Optional[str],
|
|
202
|
+
git: bool,
|
|
203
|
+
output: Optional[str],
|
|
171
204
|
simple: bool,
|
|
172
|
-
) -> Optional[Tuple[
|
|
205
|
+
) -> Optional[Tuple[Any, float, str]]:
|
|
173
206
|
"""
|
|
174
|
-
Update
|
|
207
|
+
Update the original prompt file based on code changes.
|
|
175
208
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
1. **Single-File Mode:** When you provide at least a code file, it updates
|
|
179
|
-
or generates a single prompt.
|
|
180
|
-
- `pdd update <CODE_FILE>`: Generates a new prompt for the code.
|
|
181
|
-
- `pdd update [PROMPT_FILE] <CODE_FILE>`: Updates prompt based on code.
|
|
182
|
-
- `pdd update [PROMPT_FILE] <CODE_FILE> <ORIGINAL_CODE_FILE>`: Updates prompt using explicit original code.
|
|
183
|
-
|
|
184
|
-
2. **Repository-Wide Mode:** When you provide no file arguments, it scans the
|
|
185
|
-
entire repository, finds all code/prompt pairs, creates missing prompts,
|
|
186
|
-
and updates them all based on the latest git changes.
|
|
187
|
-
- `pdd update`: Updates all prompts for modified files in the repo.
|
|
209
|
+
Repo-wide mode (no args): Scan entire repo.
|
|
210
|
+
Single-file mode (1 arg): Update prompt for specific code file.
|
|
188
211
|
"""
|
|
189
|
-
|
|
190
|
-
command_name = "update"
|
|
212
|
+
ctx.ensure_object(dict)
|
|
191
213
|
try:
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
214
|
+
# Handle argument counts per modify_python.prompt spec (aligned with README)
|
|
215
|
+
if len(files) == 0:
|
|
216
|
+
# Repo-wide mode
|
|
217
|
+
is_repo_mode = True
|
|
218
|
+
input_prompt_file = None
|
|
219
|
+
modified_code_file = None
|
|
220
|
+
input_code_file = None
|
|
221
|
+
elif len(files) == 1:
|
|
222
|
+
# Regeneration mode: just the code file
|
|
223
|
+
is_repo_mode = False
|
|
224
|
+
input_prompt_file = None
|
|
225
|
+
modified_code_file = files[0]
|
|
226
|
+
input_code_file = None
|
|
227
|
+
elif len(files) == 2:
|
|
228
|
+
# Git-based update: prompt + modified_code (requires --git)
|
|
229
|
+
if not git:
|
|
230
|
+
raise click.UsageError(
|
|
231
|
+
"Two arguments require --git flag: pdd update --git <prompt> <modified_code>"
|
|
232
|
+
)
|
|
233
|
+
is_repo_mode = False
|
|
234
|
+
input_prompt_file = files[0]
|
|
235
|
+
modified_code_file = files[1]
|
|
236
|
+
input_code_file = None
|
|
237
|
+
elif len(files) == 3:
|
|
238
|
+
# Manual update: prompt + modified_code + original_code
|
|
239
|
+
if git:
|
|
240
|
+
raise click.UsageError(
|
|
241
|
+
"Cannot use --git with 3 arguments (--git and original_code are mutually exclusive)"
|
|
242
|
+
)
|
|
243
|
+
is_repo_mode = False
|
|
244
|
+
input_prompt_file = files[0]
|
|
245
|
+
modified_code_file = files[1]
|
|
246
|
+
input_code_file = files[2]
|
|
200
247
|
else:
|
|
201
|
-
|
|
202
|
-
actual_input_prompt_file = input_prompt_file
|
|
203
|
-
|
|
204
|
-
is_repo_mode = actual_input_prompt_file is None and actual_modified_code_file is None
|
|
248
|
+
raise click.UsageError("Too many arguments. Max 3: <prompt> <modified_code> <original_code>")
|
|
205
249
|
|
|
250
|
+
# Validate mode-specific options
|
|
206
251
|
if is_repo_mode:
|
|
207
|
-
|
|
252
|
+
# Repo-wide mode: --git and --output are not allowed
|
|
253
|
+
if git:
|
|
254
|
+
raise click.UsageError(
|
|
255
|
+
"Cannot use --git in repository-wide mode"
|
|
256
|
+
)
|
|
257
|
+
if output:
|
|
208
258
|
raise click.UsageError(
|
|
209
|
-
"Cannot use
|
|
259
|
+
"Cannot use --output in repository-wide mode"
|
|
260
|
+
)
|
|
261
|
+
else:
|
|
262
|
+
# File modes: --extensions and --directory are not allowed
|
|
263
|
+
if extensions:
|
|
264
|
+
raise click.UsageError(
|
|
265
|
+
"--extensions can only be used in repository-wide mode"
|
|
266
|
+
)
|
|
267
|
+
if directory:
|
|
268
|
+
raise click.UsageError(
|
|
269
|
+
"--directory can only be used in repository-wide mode"
|
|
210
270
|
)
|
|
211
|
-
elif extensions:
|
|
212
|
-
raise click.UsageError("--extensions can only be used in repository-wide mode (when no files are provided).")
|
|
213
271
|
|
|
214
|
-
|
|
272
|
+
# Call update_main with correct parameters
|
|
273
|
+
result, cost, model = update_main(
|
|
215
274
|
ctx=ctx,
|
|
216
|
-
input_prompt_file=
|
|
217
|
-
modified_code_file=
|
|
275
|
+
input_prompt_file=input_prompt_file,
|
|
276
|
+
modified_code_file=modified_code_file,
|
|
218
277
|
input_code_file=input_code_file,
|
|
219
278
|
output=output,
|
|
220
|
-
use_git=
|
|
279
|
+
use_git=git,
|
|
221
280
|
repo=is_repo_mode,
|
|
222
281
|
extensions=extensions,
|
|
223
|
-
|
|
282
|
+
directory=directory,
|
|
283
|
+
simple=simple
|
|
224
284
|
)
|
|
225
|
-
|
|
285
|
+
|
|
286
|
+
return result, cost, model
|
|
287
|
+
|
|
226
288
|
except click.Abort:
|
|
227
289
|
raise
|
|
228
|
-
except
|
|
229
|
-
handle_error(
|
|
230
|
-
return None
|
|
290
|
+
except Exception as e:
|
|
291
|
+
handle_error(e, "update", ctx.obj.get("quiet", False))
|
|
292
|
+
return None
|