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.
- 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 +73 -21
- 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 +258 -82
- 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 -63
- pdd/data/llm_model.csv +20 -18
- pdd/detect_change_main.py +5 -4
- pdd/fix_code_loop.py +330 -76
- pdd/fix_error_loop.py +207 -61
- 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 +306 -272
- pdd/fix_verification_main.py +28 -9
- pdd/generate_output_paths.py +93 -10
- pdd/generate_test.py +16 -5
- pdd/get_jwt_token.py +9 -2
- pdd/get_run_command.py +73 -0
- pdd/get_test_command.py +68 -0
- pdd/git_update.py +70 -19
- pdd/incremental_code_generator.py +2 -2
- pdd/insert_includes.py +11 -3
- pdd/llm_invoke.py +1269 -103
- 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 +100 -905
- pdd/prompts/detect_change_LLM.prompt +122 -20
- pdd/prompts/example_generator_LLM.prompt +22 -1
- pdd/prompts/extract_code_LLM.prompt +5 -1
- pdd/prompts/extract_program_code_fix_LLM.prompt +7 -1
- 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 +4 -2
- pdd/prompts/fix_errors_from_unit_tests_LLM.prompt +8 -0
- pdd/prompts/fix_verification_errors_LLM.prompt +22 -0
- pdd/prompts/generate_test_LLM.prompt +21 -6
- pdd/prompts/increase_tests_LLM.prompt +1 -5
- pdd/prompts/insert_includes_LLM.prompt +228 -108
- pdd/prompts/trace_LLM.prompt +25 -22
- pdd/prompts/unfinished_prompt_LLM.prompt +85 -1
- pdd/prompts/update_prompt_LLM.prompt +22 -1
- pdd/pytest_output.py +127 -12
- 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 +49 -6
- pdd/sync_determine_operation.py +543 -98
- pdd/sync_main.py +81 -31
- pdd/sync_orchestration.py +1334 -751
- 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.45.dist-info → pdd_cli-0.0.90.dist-info}/METADATA +19 -6
- pdd_cli-0.0.90.dist-info/RECORD +153 -0
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/licenses/LICENSE +1 -1
- pdd_cli-0.0.45.dist-info/RECORD +0 -116
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.45.dist-info → pdd_cli-0.0.90.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Templates command group.
|
|
3
|
+
"""
|
|
4
|
+
import click
|
|
5
|
+
from rich import box
|
|
6
|
+
from rich.table import Table
|
|
7
|
+
from rich.text import Text
|
|
8
|
+
from rich.markup import escape
|
|
9
|
+
from typing import Optional, List, Tuple, Any
|
|
10
|
+
|
|
11
|
+
from .. import template_registry
|
|
12
|
+
from ..core.errors import handle_error, console
|
|
13
|
+
|
|
14
|
+
@click.group(name="templates")
|
|
15
|
+
def templates_group():
|
|
16
|
+
"""Manage packaged and project templates."""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@templates_group.command("list")
|
|
21
|
+
@click.option("--json", "as_json", is_flag=True, help="Output as JSON")
|
|
22
|
+
@click.option("--filter", "filter_tag", type=str, default=None, help="Filter by tag")
|
|
23
|
+
def templates_list(as_json: bool, filter_tag: Optional[str]):
|
|
24
|
+
try:
|
|
25
|
+
items = template_registry.list_templates(filter_tag)
|
|
26
|
+
if as_json:
|
|
27
|
+
import json as _json
|
|
28
|
+
click.echo(_json.dumps(items, indent=2))
|
|
29
|
+
else:
|
|
30
|
+
if not items:
|
|
31
|
+
console.print("[info]No templates found.[/info]")
|
|
32
|
+
return
|
|
33
|
+
console.print("[info]Available Templates:[/info]")
|
|
34
|
+
for it in items:
|
|
35
|
+
# Print the template name on its own line to avoid Rich wrapping
|
|
36
|
+
name_line = Text(f"- {it['name']}", style="bold", no_wrap=True)
|
|
37
|
+
console.print(name_line)
|
|
38
|
+
# Print details on the next line(s) with a small indent; wrapping is fine here
|
|
39
|
+
version = it.get("version", "")
|
|
40
|
+
description = it.get("description", "")
|
|
41
|
+
tags = ", ".join(it.get("tags", []))
|
|
42
|
+
details_parts = []
|
|
43
|
+
if version:
|
|
44
|
+
details_parts.append(f"({version})")
|
|
45
|
+
if description:
|
|
46
|
+
details_parts.append(description)
|
|
47
|
+
if tags:
|
|
48
|
+
details_parts.append(f"[{tags}]")
|
|
49
|
+
if details_parts:
|
|
50
|
+
console.print(" " + " — ".join(details_parts))
|
|
51
|
+
except Exception as e:
|
|
52
|
+
handle_error(e, "templates list", False)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@templates_group.command("show")
|
|
56
|
+
@click.argument("name", type=str)
|
|
57
|
+
def templates_show(name: str):
|
|
58
|
+
try:
|
|
59
|
+
data = template_registry.show_template(name)
|
|
60
|
+
summary = data.get("summary", {})
|
|
61
|
+
|
|
62
|
+
def _render_key_value_table(title: Optional[str], items: List[Tuple[str, Any]], *, highlight_path: bool = False):
|
|
63
|
+
"""Render a 2-column Rich table for key/value pairs."""
|
|
64
|
+
|
|
65
|
+
table = Table(show_header=False, box=box.SIMPLE, expand=True)
|
|
66
|
+
table.add_column("Field", style="info", no_wrap=True)
|
|
67
|
+
table.add_column("Value", overflow="fold")
|
|
68
|
+
|
|
69
|
+
added_rows = False
|
|
70
|
+
for label, value in items:
|
|
71
|
+
if value in (None, "", [], {}):
|
|
72
|
+
continue
|
|
73
|
+
if isinstance(value, (list, tuple)):
|
|
74
|
+
value_str = ", ".join(str(v) for v in value)
|
|
75
|
+
else:
|
|
76
|
+
value_str = str(value)
|
|
77
|
+
|
|
78
|
+
if highlight_path and label.lower() == "path":
|
|
79
|
+
value_markup = f"[path]{escape(value_str)}[/path]"
|
|
80
|
+
else:
|
|
81
|
+
value_markup = escape(value_str)
|
|
82
|
+
|
|
83
|
+
table.add_row(label, value_markup)
|
|
84
|
+
added_rows = True
|
|
85
|
+
|
|
86
|
+
if added_rows:
|
|
87
|
+
if title:
|
|
88
|
+
console.print(f"[info]{title}[/info]")
|
|
89
|
+
console.print(table)
|
|
90
|
+
|
|
91
|
+
summary_items = [
|
|
92
|
+
("Name", summary.get("name")),
|
|
93
|
+
("Description", summary.get("description")),
|
|
94
|
+
("Version", summary.get("version")),
|
|
95
|
+
("Tags", summary.get("tags", [])),
|
|
96
|
+
("Language", summary.get("language")),
|
|
97
|
+
("Output", summary.get("output")),
|
|
98
|
+
("Path", summary.get("path")),
|
|
99
|
+
]
|
|
100
|
+
_render_key_value_table("Template Summary:", summary_items, highlight_path=True)
|
|
101
|
+
|
|
102
|
+
if data.get("variables"):
|
|
103
|
+
console.print("\n[info]Variables:[/info]")
|
|
104
|
+
variables_table = Table(box=box.SIMPLE_HEAD, show_lines=False, expand=True)
|
|
105
|
+
variables_table.add_column("Name", style="bold", no_wrap=True)
|
|
106
|
+
variables_table.add_column("Required", style="info", no_wrap=True)
|
|
107
|
+
variables_table.add_column("Type", no_wrap=True)
|
|
108
|
+
variables_table.add_column("Description", overflow="fold")
|
|
109
|
+
variables_table.add_column("Default/Examples", overflow="fold")
|
|
110
|
+
|
|
111
|
+
for var_name, var_meta in data["variables"].items():
|
|
112
|
+
required = var_meta.get("required")
|
|
113
|
+
if required is True:
|
|
114
|
+
required_str = "Yes"
|
|
115
|
+
elif required is False:
|
|
116
|
+
required_str = "No"
|
|
117
|
+
else:
|
|
118
|
+
required_str = "-"
|
|
119
|
+
|
|
120
|
+
var_type = escape(str(var_meta.get("type", "-")))
|
|
121
|
+
description = escape(str(var_meta.get("description", "")))
|
|
122
|
+
|
|
123
|
+
default_parts: List[str] = []
|
|
124
|
+
default_value = var_meta.get("default")
|
|
125
|
+
if default_value not in (None, ""):
|
|
126
|
+
default_parts.append(f"default: {default_value}")
|
|
127
|
+
|
|
128
|
+
examples_value = var_meta.get("examples")
|
|
129
|
+
if examples_value:
|
|
130
|
+
if isinstance(examples_value, (list, tuple)):
|
|
131
|
+
examples_str = ", ".join(str(example) for example in examples_value)
|
|
132
|
+
else:
|
|
133
|
+
examples_str = str(examples_value)
|
|
134
|
+
default_parts.append(f"examples: {examples_str}")
|
|
135
|
+
|
|
136
|
+
example_paths_value = var_meta.get("example_paths")
|
|
137
|
+
if example_paths_value:
|
|
138
|
+
if isinstance(example_paths_value, (list, tuple)):
|
|
139
|
+
example_paths_str = ", ".join(str(example) for example in example_paths_value)
|
|
140
|
+
else:
|
|
141
|
+
example_paths_str = str(example_paths_value)
|
|
142
|
+
default_parts.append(f"paths: {example_paths_str}")
|
|
143
|
+
|
|
144
|
+
default_examples = "\n".join(default_parts) if default_parts else "-"
|
|
145
|
+
|
|
146
|
+
variables_table.add_row(
|
|
147
|
+
escape(str(var_name)),
|
|
148
|
+
required_str,
|
|
149
|
+
var_type,
|
|
150
|
+
description,
|
|
151
|
+
escape(default_examples),
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
console.print(variables_table)
|
|
155
|
+
|
|
156
|
+
if data.get("usage"):
|
|
157
|
+
console.print("\n[info]Usage:[/info]")
|
|
158
|
+
usage = data["usage"]
|
|
159
|
+
if isinstance(usage, dict):
|
|
160
|
+
for group_name, entries in usage.items():
|
|
161
|
+
console.print(f"[bold]{escape(str(group_name))}[/bold]")
|
|
162
|
+
usage_table = Table(box=box.SIMPLE, show_lines=False, expand=True)
|
|
163
|
+
usage_table.add_column("Name", style="bold", no_wrap=True)
|
|
164
|
+
usage_table.add_column("Command", overflow="fold")
|
|
165
|
+
|
|
166
|
+
if isinstance(entries, (list, tuple)):
|
|
167
|
+
iterable_entries = entries
|
|
168
|
+
else:
|
|
169
|
+
iterable_entries = [entries]
|
|
170
|
+
|
|
171
|
+
for entry in iterable_entries:
|
|
172
|
+
if isinstance(entry, dict):
|
|
173
|
+
name_value = escape(str(entry.get("name", "")))
|
|
174
|
+
command_value = escape(str(entry.get("command", "")))
|
|
175
|
+
else:
|
|
176
|
+
name_value = "-"
|
|
177
|
+
command_value = escape(str(entry))
|
|
178
|
+
usage_table.add_row(name_value, f"[command]{command_value}[/command]")
|
|
179
|
+
|
|
180
|
+
if usage_table.row_count:
|
|
181
|
+
console.print(usage_table)
|
|
182
|
+
else:
|
|
183
|
+
console.print(usage)
|
|
184
|
+
|
|
185
|
+
if data.get("discover"):
|
|
186
|
+
console.print("\n[info]Discover:[/info]")
|
|
187
|
+
discover = data["discover"]
|
|
188
|
+
if isinstance(discover, dict):
|
|
189
|
+
discover_items = [(str(key), value) for key, value in discover.items()]
|
|
190
|
+
_render_key_value_table(None, discover_items)
|
|
191
|
+
else:
|
|
192
|
+
console.print(discover)
|
|
193
|
+
if data.get("output_schema"):
|
|
194
|
+
console.print("\n[info]Output Schema:[/info]")
|
|
195
|
+
try:
|
|
196
|
+
import json as _json
|
|
197
|
+
console.print(_json.dumps(data["output_schema"], indent=2))
|
|
198
|
+
except Exception:
|
|
199
|
+
console.print(str(data["output_schema"]))
|
|
200
|
+
if data.get("notes"):
|
|
201
|
+
console.print("\n[info]Notes:[/info]")
|
|
202
|
+
console.print(data["notes"]) # plain text
|
|
203
|
+
except Exception as e:
|
|
204
|
+
handle_error(e, "templates show", False)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
@templates_group.command("copy")
|
|
208
|
+
@click.argument("name", type=str)
|
|
209
|
+
@click.option("--to", "dest_dir", type=click.Path(file_okay=False), required=True)
|
|
210
|
+
def templates_copy(name: str, dest_dir: str):
|
|
211
|
+
try:
|
|
212
|
+
dest = template_registry.copy_template(name, dest_dir)
|
|
213
|
+
console.print(f"[success]Copied to:[/success] {dest}")
|
|
214
|
+
except Exception as e:
|
|
215
|
+
handle_error(e, "templates copy", False)
|
pdd/commands/utility.py
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility commands (install_completion, verify/fix-verification).
|
|
3
|
+
"""
|
|
4
|
+
import click
|
|
5
|
+
from typing import Optional, Tuple
|
|
6
|
+
|
|
7
|
+
from ..fix_verification_main import fix_verification_main
|
|
8
|
+
from ..track_cost import track_cost
|
|
9
|
+
from ..core.errors import handle_error
|
|
10
|
+
|
|
11
|
+
@click.command("install_completion")
|
|
12
|
+
@click.pass_context
|
|
13
|
+
def install_completion_cmd(ctx: click.Context):
|
|
14
|
+
"""Install shell completion for the PDD CLI."""
|
|
15
|
+
try:
|
|
16
|
+
from .. import cli as cli_module # Import parent module for proper patching
|
|
17
|
+
quiet = ctx.obj.get("quiet", False)
|
|
18
|
+
# Call through cli_module so patches to pdd.cli.install_completion work
|
|
19
|
+
cli_module.install_completion(quiet=quiet)
|
|
20
|
+
except Exception as e:
|
|
21
|
+
handle_error(e, "install_completion", ctx.obj.get("quiet", False))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@click.command("verify")
|
|
25
|
+
@click.argument("prompt_file", type=click.Path(exists=True, dir_okay=False))
|
|
26
|
+
@click.argument("code_file", type=click.Path(exists=True, dir_okay=False))
|
|
27
|
+
@click.argument("verification_program", type=click.Path(exists=True, dir_okay=False))
|
|
28
|
+
@click.option(
|
|
29
|
+
"--output-code",
|
|
30
|
+
type=click.Path(writable=True),
|
|
31
|
+
default=None,
|
|
32
|
+
help="Specify where to save the verified code file (file or directory).",
|
|
33
|
+
)
|
|
34
|
+
@click.option(
|
|
35
|
+
"--output-program",
|
|
36
|
+
type=click.Path(writable=True),
|
|
37
|
+
default=None,
|
|
38
|
+
help="Specify where to save the verified program file (file or directory).",
|
|
39
|
+
)
|
|
40
|
+
@click.option(
|
|
41
|
+
"--output-results",
|
|
42
|
+
type=click.Path(writable=True),
|
|
43
|
+
default=None,
|
|
44
|
+
help="Specify where to save the results log (file or directory).",
|
|
45
|
+
)
|
|
46
|
+
@click.option(
|
|
47
|
+
"--max-attempts",
|
|
48
|
+
type=int,
|
|
49
|
+
default=3,
|
|
50
|
+
show_default=True,
|
|
51
|
+
help="Maximum number of verification attempts.",
|
|
52
|
+
)
|
|
53
|
+
@click.option(
|
|
54
|
+
"--budget",
|
|
55
|
+
type=float,
|
|
56
|
+
default=5.0,
|
|
57
|
+
show_default=True,
|
|
58
|
+
help="Maximum cost allowed for the verification process.",
|
|
59
|
+
)
|
|
60
|
+
@click.option(
|
|
61
|
+
"--agentic-fallback/--no-agentic-fallback",
|
|
62
|
+
is_flag=True,
|
|
63
|
+
default=True,
|
|
64
|
+
help="Enable agentic fallback if the primary fix mechanism fails.",
|
|
65
|
+
)
|
|
66
|
+
@click.pass_context
|
|
67
|
+
@track_cost
|
|
68
|
+
def verify(
|
|
69
|
+
ctx: click.Context,
|
|
70
|
+
prompt_file: str,
|
|
71
|
+
code_file: str,
|
|
72
|
+
verification_program: str,
|
|
73
|
+
output_code: Optional[str],
|
|
74
|
+
output_program: Optional[str],
|
|
75
|
+
output_results: Optional[str],
|
|
76
|
+
max_attempts: int,
|
|
77
|
+
budget: float,
|
|
78
|
+
agentic_fallback: bool,
|
|
79
|
+
) -> Optional[Tuple]:
|
|
80
|
+
"""Verify code using a verification program."""
|
|
81
|
+
try:
|
|
82
|
+
# verify command implies a loop if max_attempts > 1, but let's enable loop by default
|
|
83
|
+
# as it's the more powerful mode and matches the CLI args provided (max_attempts).
|
|
84
|
+
# verification_program positional arg acts as both program_file (to run) and verification_program (reference)
|
|
85
|
+
success, prog_code, code_content, attempts, total_cost, model_name = fix_verification_main(
|
|
86
|
+
ctx=ctx,
|
|
87
|
+
prompt_file=prompt_file,
|
|
88
|
+
code_file=code_file,
|
|
89
|
+
program_file=verification_program,
|
|
90
|
+
output_code=output_code,
|
|
91
|
+
output_program=output_program,
|
|
92
|
+
output_results=output_results,
|
|
93
|
+
loop=True,
|
|
94
|
+
verification_program=verification_program,
|
|
95
|
+
max_attempts=max_attempts,
|
|
96
|
+
budget=budget,
|
|
97
|
+
agentic_fallback=agentic_fallback,
|
|
98
|
+
)
|
|
99
|
+
result = {
|
|
100
|
+
"success": success,
|
|
101
|
+
"program_code": prog_code,
|
|
102
|
+
"code_content": code_content,
|
|
103
|
+
"attempts": attempts,
|
|
104
|
+
}
|
|
105
|
+
return result, total_cost, model_name
|
|
106
|
+
except click.Abort:
|
|
107
|
+
raise
|
|
108
|
+
except Exception as exception:
|
|
109
|
+
handle_error(exception, "verify", ctx.obj.get("quiet", False))
|
|
110
|
+
return None
|
pdd/config_resolution.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized config resolution for all commands.
|
|
3
|
+
|
|
4
|
+
Single source of truth for resolving strength, temperature, and other config values.
|
|
5
|
+
This module ensures consistent priority ordering across all commands:
|
|
6
|
+
1. CLI global options (--strength, --temperature) - highest priority
|
|
7
|
+
2. pddrc context defaults - medium priority
|
|
8
|
+
3. Hardcoded defaults - lowest priority
|
|
9
|
+
"""
|
|
10
|
+
from typing import Dict, Any, Optional
|
|
11
|
+
import click
|
|
12
|
+
|
|
13
|
+
from . import DEFAULT_STRENGTH, DEFAULT_TEMPERATURE, DEFAULT_TIME
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def resolve_effective_config(
|
|
17
|
+
ctx: click.Context,
|
|
18
|
+
resolved_config: Dict[str, Any],
|
|
19
|
+
param_overrides: Optional[Dict[str, Any]] = None
|
|
20
|
+
) -> Dict[str, Any]:
|
|
21
|
+
"""
|
|
22
|
+
Resolve effective config values with proper priority.
|
|
23
|
+
|
|
24
|
+
Priority (highest to lowest):
|
|
25
|
+
1. Command parameter overrides (e.g., strength kwarg)
|
|
26
|
+
2. CLI global options (--strength stored in ctx.obj)
|
|
27
|
+
3. pddrc context defaults (from resolved_config)
|
|
28
|
+
4. Hardcoded defaults
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
ctx: Click context with CLI options in ctx.obj
|
|
32
|
+
resolved_config: Config returned by construct_paths (contains pddrc values)
|
|
33
|
+
param_overrides: Optional command-specific parameter overrides
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
Dict with resolved values for strength, temperature, time
|
|
37
|
+
"""
|
|
38
|
+
ctx_obj = ctx.obj if ctx.obj else {}
|
|
39
|
+
param_overrides = param_overrides or {}
|
|
40
|
+
|
|
41
|
+
def resolve_value(key: str, default: Any) -> Any:
|
|
42
|
+
# Priority 1: Command parameter override
|
|
43
|
+
if key in param_overrides and param_overrides[key] is not None:
|
|
44
|
+
return param_overrides[key]
|
|
45
|
+
# Priority 2: CLI global option (only if key IS in ctx.obj - meaning CLI passed it)
|
|
46
|
+
if key in ctx_obj:
|
|
47
|
+
return ctx_obj[key]
|
|
48
|
+
# Priority 3: pddrc context default
|
|
49
|
+
if key in resolved_config and resolved_config[key] is not None:
|
|
50
|
+
return resolved_config[key]
|
|
51
|
+
# Priority 4: Hardcoded default
|
|
52
|
+
return default
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
"strength": resolve_value("strength", DEFAULT_STRENGTH),
|
|
56
|
+
"temperature": resolve_value("temperature", DEFAULT_TEMPERATURE),
|
|
57
|
+
"time": resolve_value("time", DEFAULT_TIME),
|
|
58
|
+
}
|
pdd/conflicts_main.py
CHANGED
|
@@ -8,7 +8,7 @@ from .construct_paths import construct_paths
|
|
|
8
8
|
from .conflicts_in_prompts import conflicts_in_prompts
|
|
9
9
|
from . import DEFAULT_TIME, DEFAULT_STRENGTH
|
|
10
10
|
|
|
11
|
-
def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optional[str], verbose: bool = False) -> Tuple[List[Dict], float, str]:
|
|
11
|
+
def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optional[str], verbose: bool = False, language: Optional[str] = None) -> Tuple[List[Dict], float, str]:
|
|
12
12
|
"""
|
|
13
13
|
Main function to analyze conflicts between two prompts.
|
|
14
14
|
|
|
@@ -17,6 +17,7 @@ def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optio
|
|
|
17
17
|
:param prompt2: Path to the second prompt file.
|
|
18
18
|
:param output: Optional path to save the output CSV file.
|
|
19
19
|
:param verbose: Optional parameter to control verbosity (default: False).
|
|
20
|
+
:param language: Optional language hint for file processing.
|
|
20
21
|
:return: A tuple containing the list of conflicts, total cost, and model name used.
|
|
21
22
|
"""
|
|
22
23
|
try:
|
|
@@ -28,12 +29,16 @@ def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optio
|
|
|
28
29
|
command_options = {
|
|
29
30
|
"output": output
|
|
30
31
|
}
|
|
32
|
+
if language:
|
|
33
|
+
command_options["language"] = language
|
|
34
|
+
|
|
31
35
|
resolved_config, input_strings, output_file_paths, _ = construct_paths(
|
|
32
36
|
input_file_paths=input_file_paths,
|
|
33
37
|
force=ctx.obj.get('force', False),
|
|
34
38
|
quiet=ctx.obj.get('quiet', False),
|
|
35
39
|
command="conflicts",
|
|
36
|
-
command_options=command_options
|
|
40
|
+
command_options=command_options,
|
|
41
|
+
context_override=ctx.obj.get('context')
|
|
37
42
|
)
|
|
38
43
|
|
|
39
44
|
# Load input files
|
|
@@ -91,4 +96,4 @@ def conflicts_main(ctx: click.Context, prompt1: str, prompt2: str, output: Optio
|
|
|
91
96
|
except Exception as e:
|
|
92
97
|
if not ctx.obj.get('quiet', False):
|
|
93
98
|
rprint(f"[bold red]Error:[/bold red] {str(e)}")
|
|
94
|
-
sys.exit(1)
|
|
99
|
+
sys.exit(1)
|