pdd-cli 0.0.90__py3-none-any.whl → 0.0.118__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 +497 -0
- pdd/agentic_change.py +231 -0
- pdd/agentic_change_orchestrator.py +526 -0
- pdd/agentic_common.py +521 -786
- pdd/agentic_e2e_fix.py +319 -0
- pdd/agentic_e2e_fix_orchestrator.py +426 -0
- pdd/agentic_fix.py +118 -3
- pdd/agentic_update.py +25 -8
- pdd/architecture_sync.py +565 -0
- pdd/auth_service.py +210 -0
- pdd/auto_deps_main.py +63 -53
- pdd/auto_include.py +185 -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 +87 -29
- pdd/commands/auth.py +309 -0
- pdd/commands/connect.py +290 -0
- pdd/commands/fix.py +136 -113
- pdd/commands/maintenance.py +3 -2
- pdd/commands/misc.py +8 -0
- pdd/commands/modify.py +190 -164
- pdd/commands/sessions.py +284 -0
- 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 +27 -3
- pdd/core/cloud.py +237 -0
- 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 +204 -4
- 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-DQ3wkeQ2.js +449 -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 +459 -95
- pdd/load_prompt_template.py +15 -34
- pdd/path_resolution.py +140 -0
- pdd/postprocess.py +4 -1
- 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 +131 -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 +20 -1
- pdd/prompts/generate_test_from_example_LLM.prompt +115 -0
- pdd/prompts/insert_includes_LLM.prompt +262 -252
- pdd/prompts/prompt_code_diff_LLM.prompt +119 -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 +1322 -0
- pdd/server/routes/websocket.py +473 -0
- pdd/server/security.py +243 -0
- pdd/server/terminal_spawner.py +209 -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 +136 -75
- 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 +23 -5
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/METADATA +15 -10
- pdd_cli-0.0.118.dist-info/RECORD +227 -0
- pdd_cli-0.0.90.dist-info/RECORD +0 -153
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/licenses/LICENSE +0 -0
- {pdd_cli-0.0.90.dist-info → pdd_cli-0.0.118.dist-info}/top_level.txt +0 -0
pdd/commands/modify.py
CHANGED
|
@@ -1,32 +1,28 @@
|
|
|
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
|
|
13
17
|
|
|
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
|
-
)
|
|
18
|
+
console = Console()
|
|
19
|
+
|
|
20
|
+
@click.command()
|
|
21
|
+
@click.argument("input_prompt", type=click.Path(exists=True))
|
|
22
|
+
@click.argument("input_code", type=click.Path(exists=True))
|
|
23
|
+
@click.argument("example_code", type=click.Path(exists=True))
|
|
24
|
+
@click.option("--output-sub", help="Optional path for saving the sub-prompt.")
|
|
25
|
+
@click.option("--output-modified", help="Optional path for saving the modified prompt.")
|
|
30
26
|
@click.pass_context
|
|
31
27
|
@track_cost
|
|
32
28
|
def split(
|
|
@@ -36,13 +32,15 @@ def split(
|
|
|
36
32
|
example_code: str,
|
|
37
33
|
output_sub: Optional[str],
|
|
38
34
|
output_modified: Optional[str],
|
|
39
|
-
) -> Optional[Tuple[
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
) -> Optional[Tuple[Any, float, str]]:
|
|
36
|
+
"""
|
|
37
|
+
Split large complex prompt files into smaller, more manageable prompt files.
|
|
38
|
+
"""
|
|
39
|
+
ctx.ensure_object(dict)
|
|
43
40
|
try:
|
|
41
|
+
# Call split_main with required arguments
|
|
44
42
|
result_data, total_cost, model_name = split_main(
|
|
45
|
-
ctx
|
|
43
|
+
ctx,
|
|
46
44
|
input_prompt_file=input_prompt,
|
|
47
45
|
input_code_file=input_code,
|
|
48
46
|
example_code_file=example_code,
|
|
@@ -50,181 +48,209 @@ def split(
|
|
|
50
48
|
output_modified=output_modified,
|
|
51
49
|
)
|
|
52
50
|
return result_data, total_cost, model_name
|
|
51
|
+
|
|
53
52
|
except click.Abort:
|
|
54
53
|
raise
|
|
55
54
|
except Exception as e:
|
|
56
|
-
handle_error(e,
|
|
55
|
+
handle_error(e, "split", ctx.obj.get("quiet", False))
|
|
57
56
|
return None
|
|
58
57
|
|
|
59
58
|
|
|
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
|
-
)
|
|
59
|
+
@click.command()
|
|
60
|
+
@click.argument("args", nargs=-1)
|
|
61
|
+
@click.option("--manual", is_flag=True, default=False, help="Use legacy manual mode.")
|
|
62
|
+
@click.option("--budget", type=float, default=5.0, help="Budget for the operation.")
|
|
63
|
+
@click.option("--output", help="Output path.")
|
|
64
|
+
@click.option("--csv", is_flag=True, help="Use CSV input for batch processing.")
|
|
65
|
+
@click.option("--timeout-adder", type=float, default=0.0, help="Additional seconds to add to each step's timeout (agentic mode only).")
|
|
66
|
+
@click.option("--no-github-state", is_flag=True, default=False, help="Disable GitHub state persistence (agentic mode only).")
|
|
84
67
|
@click.pass_context
|
|
85
68
|
@track_cost
|
|
86
69
|
def change(
|
|
87
70
|
ctx: click.Context,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
input_prompt_file: Optional[str],
|
|
91
|
-
output: Optional[str],
|
|
92
|
-
use_csv: bool,
|
|
71
|
+
args: Tuple[str, ...],
|
|
72
|
+
manual: bool,
|
|
93
73
|
budget: float,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
74
|
+
output: Optional[str],
|
|
75
|
+
csv: bool,
|
|
76
|
+
timeout_adder: float,
|
|
77
|
+
no_github_state: bool,
|
|
78
|
+
) -> Optional[Tuple[Any, float, str]]:
|
|
79
|
+
"""
|
|
80
|
+
Modify an input prompt file based on a change prompt or issue.
|
|
81
|
+
|
|
82
|
+
Agentic Mode (default):
|
|
83
|
+
pdd change ISSUE_URL
|
|
84
|
+
|
|
85
|
+
Manual Mode (--manual):
|
|
86
|
+
pdd change --manual CHANGE_PROMPT_FILE INPUT_CODE_FILE [INPUT_PROMPT_FILE]
|
|
87
|
+
"""
|
|
88
|
+
ctx.ensure_object(dict)
|
|
89
|
+
|
|
98
90
|
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
|
-
|
|
91
|
+
# Set budget in context for manual mode usage
|
|
92
|
+
ctx.obj["budget"] = budget
|
|
93
|
+
|
|
94
|
+
quiet = ctx.obj.get("quiet", False)
|
|
95
|
+
verbose = ctx.obj.get("verbose", False)
|
|
96
|
+
|
|
97
|
+
if manual:
|
|
98
|
+
# Manual Mode Validation and Execution
|
|
99
|
+
if csv:
|
|
100
|
+
# CSV Mode: Expecting CSV_FILE and CODE_DIRECTORY (no input_prompt)
|
|
101
|
+
if len(args) == 3:
|
|
102
|
+
raise click.UsageError("Cannot use --csv and specify an INPUT_PROMPT_FILE simultaneously.")
|
|
103
|
+
if len(args) != 2:
|
|
104
|
+
raise click.UsageError("CSV mode requires 2 arguments: CSV_FILE CODE_DIRECTORY")
|
|
105
|
+
|
|
106
|
+
change_file, input_code = args
|
|
107
|
+
input_prompt = None
|
|
108
|
+
|
|
109
|
+
# CSV mode requires input_code to be a directory
|
|
110
|
+
if not Path(input_code).is_dir():
|
|
111
|
+
raise click.UsageError("INPUT_CODE must be a directory when using --csv")
|
|
112
|
+
else:
|
|
113
|
+
# Standard Manual Mode: Expecting 2 or 3 arguments
|
|
114
|
+
if len(args) == 3:
|
|
115
|
+
change_file, input_code, input_prompt = args
|
|
116
|
+
# Non-CSV mode requires input_code to be a file, not a directory
|
|
117
|
+
if Path(input_code).is_dir():
|
|
118
|
+
raise click.UsageError("INPUT_CODE must be a file when not using --csv")
|
|
119
|
+
elif len(args) == 2:
|
|
120
|
+
change_file, input_code = args
|
|
121
|
+
input_prompt = None
|
|
122
|
+
# Without CSV mode, input_prompt_file is required
|
|
123
|
+
raise click.UsageError("INPUT_PROMPT_FILE is required when not using --csv")
|
|
124
|
+
else:
|
|
125
|
+
raise click.UsageError(
|
|
126
|
+
"Manual mode requires 2 or 3 arguments: CHANGE_PROMPT INPUT_CODE [INPUT_PROMPT]"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Validate file existence
|
|
130
|
+
if not Path(change_file).exists():
|
|
131
|
+
raise click.UsageError(f"Change file not found: {change_file}")
|
|
132
|
+
if not Path(input_code).exists():
|
|
133
|
+
raise click.UsageError(f"Input code path not found: {input_code}")
|
|
134
|
+
if input_prompt and not Path(input_prompt).exists():
|
|
135
|
+
raise click.UsageError(f"Input prompt file not found: {input_prompt}")
|
|
136
|
+
|
|
137
|
+
# Call change_main
|
|
138
|
+
result, cost, model = change_main(
|
|
139
|
+
ctx=ctx,
|
|
140
|
+
change_prompt_file=change_file,
|
|
141
|
+
input_code=input_code,
|
|
142
|
+
input_prompt_file=input_prompt,
|
|
143
|
+
output=output,
|
|
144
|
+
use_csv=csv,
|
|
145
|
+
budget=budget
|
|
146
|
+
)
|
|
147
|
+
return result, cost, model
|
|
148
|
+
|
|
149
|
+
else:
|
|
150
|
+
# Agentic Mode Validation and Execution
|
|
151
|
+
if len(args) != 1:
|
|
152
|
+
raise click.UsageError("Agentic mode requires exactly 1 argument: ISSUE_URL")
|
|
153
|
+
|
|
154
|
+
issue_url = args[0]
|
|
155
|
+
|
|
156
|
+
# Call run_agentic_change
|
|
157
|
+
success, message, cost, model, changed_files = run_agentic_change(
|
|
158
|
+
issue_url=issue_url,
|
|
159
|
+
verbose=verbose,
|
|
160
|
+
quiet=quiet,
|
|
161
|
+
timeout_adder=timeout_adder,
|
|
162
|
+
use_github_state=not no_github_state
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Display results using click.echo as requested
|
|
166
|
+
if not quiet:
|
|
167
|
+
status = "Success" if success else "Failed"
|
|
168
|
+
click.echo(f"Status: {status}")
|
|
169
|
+
click.echo(f"Message: {message}")
|
|
170
|
+
click.echo(f"Cost: ${cost:.4f}")
|
|
171
|
+
click.echo(f"Model: {model}")
|
|
172
|
+
if changed_files:
|
|
173
|
+
click.echo("Changed files:")
|
|
174
|
+
for f in changed_files:
|
|
175
|
+
click.echo(f" - {f}")
|
|
176
|
+
|
|
177
|
+
return message, cost, model
|
|
178
|
+
|
|
125
179
|
except click.Abort:
|
|
126
180
|
raise
|
|
127
|
-
except
|
|
128
|
-
handle_error(e,
|
|
181
|
+
except Exception as e:
|
|
182
|
+
handle_error(e, "change", ctx.obj.get("quiet", False))
|
|
129
183
|
return None
|
|
130
184
|
|
|
131
185
|
|
|
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
|
-
)
|
|
186
|
+
@click.command()
|
|
187
|
+
@click.argument("files", nargs=-1)
|
|
188
|
+
@click.option("--extensions", help="Comma-separated extensions for repo mode.")
|
|
189
|
+
@click.option("--directory", help="Directory to scan for repo mode.")
|
|
190
|
+
@click.option("--git", is_flag=True, help="Use git history for original code.")
|
|
191
|
+
@click.option("--output", help="Output path for the updated prompt.")
|
|
192
|
+
@click.option("--simple", is_flag=True, default=False, help="Use legacy simple update.")
|
|
161
193
|
@click.pass_context
|
|
162
194
|
@track_cost
|
|
163
195
|
def update(
|
|
164
196
|
ctx: click.Context,
|
|
165
|
-
|
|
166
|
-
modified_code_file: Optional[str],
|
|
167
|
-
input_code_file: Optional[str],
|
|
168
|
-
output: Optional[str],
|
|
169
|
-
use_git: bool,
|
|
197
|
+
files: Tuple[str, ...],
|
|
170
198
|
extensions: Optional[str],
|
|
199
|
+
directory: Optional[str],
|
|
200
|
+
git: bool,
|
|
201
|
+
output: Optional[str],
|
|
171
202
|
simple: bool,
|
|
172
|
-
) -> Optional[Tuple[
|
|
203
|
+
) -> Optional[Tuple[Any, float, str]]:
|
|
173
204
|
"""
|
|
174
|
-
Update
|
|
175
|
-
|
|
176
|
-
This command operates in two modes:
|
|
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.
|
|
205
|
+
Update the original prompt file based on code changes.
|
|
183
206
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
and updates them all based on the latest git changes.
|
|
187
|
-
- `pdd update`: Updates all prompts for modified files in the repo.
|
|
207
|
+
Repo-wide mode (no args): Scan entire repo.
|
|
208
|
+
Single-file mode (1 arg): Update prompt for specific code file.
|
|
188
209
|
"""
|
|
189
|
-
|
|
190
|
-
command_name = "update"
|
|
210
|
+
ctx.ensure_object(dict)
|
|
191
211
|
try:
|
|
192
|
-
#
|
|
193
|
-
|
|
194
|
-
# `pdd update <CODE_FILE>` to generate a new prompt for the given code file.
|
|
195
|
-
# So if input_prompt_file has a value but modified_code_file is None,
|
|
196
|
-
# we reassign input_prompt_file to actual_modified_code_file.
|
|
197
|
-
if input_prompt_file is not None and modified_code_file is None:
|
|
198
|
-
actual_modified_code_file = input_prompt_file
|
|
199
|
-
actual_input_prompt_file = None
|
|
200
|
-
else:
|
|
201
|
-
actual_modified_code_file = modified_code_file
|
|
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
|
|
212
|
+
# Determine mode based on argument count
|
|
213
|
+
is_repo_mode = len(files) == 0
|
|
205
214
|
|
|
215
|
+
# Validate mode-specific options
|
|
206
216
|
if is_repo_mode:
|
|
207
|
-
|
|
217
|
+
# Repo-wide mode: --git and --output are not allowed
|
|
218
|
+
if git:
|
|
219
|
+
raise click.UsageError(
|
|
220
|
+
"Cannot use file-specific arguments or flags like --git in repository-wide mode"
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
# Single-file mode: --extensions and --directory are not allowed
|
|
224
|
+
if extensions:
|
|
208
225
|
raise click.UsageError(
|
|
209
|
-
"
|
|
226
|
+
"--extensions can only be used in repository-wide mode"
|
|
210
227
|
)
|
|
211
|
-
|
|
212
|
-
|
|
228
|
+
if directory:
|
|
229
|
+
raise click.UsageError(
|
|
230
|
+
"--directory can only be used in repository-wide mode"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# In single-file mode, the one arg is the modified code file
|
|
234
|
+
modified_code_file = files[0] if len(files) > 0 else None
|
|
213
235
|
|
|
214
|
-
|
|
236
|
+
# Call update_main with correct parameters
|
|
237
|
+
result, cost, model = update_main(
|
|
215
238
|
ctx=ctx,
|
|
216
|
-
input_prompt_file=
|
|
217
|
-
modified_code_file=
|
|
218
|
-
input_code_file=
|
|
239
|
+
input_prompt_file=None,
|
|
240
|
+
modified_code_file=modified_code_file,
|
|
241
|
+
input_code_file=None,
|
|
219
242
|
output=output,
|
|
220
|
-
use_git=
|
|
243
|
+
use_git=git,
|
|
221
244
|
repo=is_repo_mode,
|
|
222
245
|
extensions=extensions,
|
|
223
|
-
|
|
246
|
+
directory=directory,
|
|
247
|
+
simple=simple
|
|
224
248
|
)
|
|
225
|
-
|
|
249
|
+
|
|
250
|
+
return result, cost, model
|
|
251
|
+
|
|
226
252
|
except click.Abort:
|
|
227
253
|
raise
|
|
228
|
-
except
|
|
229
|
-
handle_error(
|
|
254
|
+
except Exception as e:
|
|
255
|
+
handle_error(e, "update", ctx.obj.get("quiet", False))
|
|
230
256
|
return None
|