pdd-cli 0.0.118__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 +1 -1
- pdd/agentic_bug_orchestrator.py +15 -6
- pdd/agentic_change_orchestrator.py +18 -7
- pdd/agentic_common.py +68 -40
- pdd/agentic_crash.py +2 -1
- pdd/agentic_e2e_fix_orchestrator.py +165 -9
- pdd/agentic_update.py +2 -1
- pdd/agentic_verify.py +3 -2
- pdd/auto_include.py +51 -0
- pdd/commands/analysis.py +32 -25
- pdd/commands/connect.py +69 -1
- pdd/commands/fix.py +31 -13
- pdd/commands/generate.py +5 -0
- pdd/commands/modify.py +47 -11
- pdd/commands/utility.py +12 -7
- pdd/core/cli.py +17 -4
- pdd/core/dump.py +68 -20
- pdd/fix_main.py +4 -2
- pdd/frontend/dist/assets/index-CUWd8al1.js +450 -0
- pdd/frontend/dist/index.html +1 -1
- pdd/llm_invoke.py +82 -12
- pdd/operation_log.py +342 -0
- pdd/postprocess.py +122 -100
- pdd/prompts/agentic_change_step12_create_pr_LLM.prompt +11 -2
- pdd/prompts/generate_test_LLM.prompt +0 -1
- pdd/prompts/generate_test_from_example_LLM.prompt +251 -0
- pdd/prompts/prompt_code_diff_LLM.prompt +29 -25
- pdd/server/routes/prompts.py +26 -1
- pdd/server/terminal_spawner.py +15 -7
- pdd/sync_orchestration.py +164 -147
- pdd/sync_order.py +304 -0
- pdd/update_main.py +48 -24
- {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/METADATA +3 -3
- {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/RECORD +37 -35
- pdd/frontend/dist/assets/index-DQ3wkeQ2.js +0 -449
- {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/WHEEL +0 -0
- {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/entry_points.txt +0 -0
- {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/licenses/LICENSE +0 -0
- {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/top_level.txt +0 -0
pdd/core/dump.py
CHANGED
|
@@ -16,6 +16,43 @@ import requests
|
|
|
16
16
|
from .. import __version__
|
|
17
17
|
from .errors import console, get_core_dump_errors
|
|
18
18
|
|
|
19
|
+
|
|
20
|
+
def garbage_collect_core_dumps(keep: int = 10) -> int:
|
|
21
|
+
"""Delete old core dumps, keeping only the most recent `keep` files.
|
|
22
|
+
|
|
23
|
+
Core dumps are sorted by modification time (mtime), and the oldest
|
|
24
|
+
files beyond the `keep` limit are deleted.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
keep: Number of core dump files to keep. Default is 10.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
The number of deleted files.
|
|
31
|
+
"""
|
|
32
|
+
core_dump_dir = Path.cwd() / ".pdd" / "core_dumps"
|
|
33
|
+
if not core_dump_dir.exists():
|
|
34
|
+
return 0
|
|
35
|
+
|
|
36
|
+
# Find all core dump files and sort by mtime (newest first)
|
|
37
|
+
dumps = sorted(
|
|
38
|
+
core_dump_dir.glob("pdd-core-*.json"),
|
|
39
|
+
key=lambda p: p.stat().st_mtime,
|
|
40
|
+
reverse=True
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Delete files beyond the keep limit
|
|
44
|
+
deleted = 0
|
|
45
|
+
for dump_file in dumps[keep:]:
|
|
46
|
+
try:
|
|
47
|
+
dump_file.unlink()
|
|
48
|
+
deleted += 1
|
|
49
|
+
except OSError:
|
|
50
|
+
# If we can't delete a file, just skip it
|
|
51
|
+
pass
|
|
52
|
+
|
|
53
|
+
return deleted
|
|
54
|
+
|
|
55
|
+
|
|
19
56
|
def _write_core_dump(
|
|
20
57
|
ctx: click.Context,
|
|
21
58
|
normalized_results: List[Any],
|
|
@@ -70,8 +107,8 @@ def _write_core_dump(
|
|
|
70
107
|
file_contents = {}
|
|
71
108
|
core_dump_files = ctx.obj.get("core_dump_files", set())
|
|
72
109
|
|
|
73
|
-
if not ctx.obj.get("quiet"):
|
|
74
|
-
console.print(f"[info]
|
|
110
|
+
if ctx.obj.get("verbose") and not ctx.obj.get("quiet"):
|
|
111
|
+
console.print(f"[info]Debug snapshot: Found {len(core_dump_files)} tracked files[/info]")
|
|
75
112
|
|
|
76
113
|
# Auto-include relevant meta files for the invoked commands
|
|
77
114
|
meta_dir = Path.cwd() / ".pdd" / "meta"
|
|
@@ -100,8 +137,8 @@ def _write_core_dump(
|
|
|
100
137
|
for file_path in core_dump_files:
|
|
101
138
|
try:
|
|
102
139
|
path = Path(file_path)
|
|
103
|
-
if not ctx.obj.get("quiet"):
|
|
104
|
-
console.print(f"[info]
|
|
140
|
+
if ctx.obj.get("verbose") and not ctx.obj.get("quiet"):
|
|
141
|
+
console.print(f"[info]Debug snapshot: Checking file {file_path}[/info]")
|
|
105
142
|
|
|
106
143
|
if path.exists() and path.is_file():
|
|
107
144
|
if path.stat().st_size < 50000: # 50KB limit
|
|
@@ -113,23 +150,23 @@ def _write_core_dump(
|
|
|
113
150
|
key = str(path)
|
|
114
151
|
|
|
115
152
|
file_contents[key] = path.read_text(encoding='utf-8')
|
|
116
|
-
if not ctx.obj.get("quiet"):
|
|
117
|
-
console.print(f"[info]
|
|
153
|
+
if ctx.obj.get("verbose") and not ctx.obj.get("quiet"):
|
|
154
|
+
console.print(f"[info]Debug snapshot: Added content for {key}[/info]")
|
|
118
155
|
except UnicodeDecodeError:
|
|
119
156
|
file_contents[str(path)] = "<binary>"
|
|
120
|
-
if not ctx.obj.get("quiet"):
|
|
121
|
-
console.print(f"[warning]
|
|
157
|
+
if ctx.obj.get("verbose") and not ctx.obj.get("quiet"):
|
|
158
|
+
console.print(f"[warning]Debug snapshot: Binary file {path}[/warning]")
|
|
122
159
|
else:
|
|
123
160
|
file_contents[str(path)] = "<too large>"
|
|
124
|
-
if not ctx.obj.get("quiet"):
|
|
125
|
-
console.print(f"[warning]
|
|
161
|
+
if ctx.obj.get("verbose") and not ctx.obj.get("quiet"):
|
|
162
|
+
console.print(f"[warning]Debug snapshot: File too large {path}[/warning]")
|
|
126
163
|
else:
|
|
127
|
-
if not ctx.obj.get("quiet"):
|
|
128
|
-
console.print(f"[warning]
|
|
164
|
+
if ctx.obj.get("verbose") and not ctx.obj.get("quiet"):
|
|
165
|
+
console.print(f"[warning]Debug snapshot: File not found or not a file: {file_path}[/warning]")
|
|
129
166
|
except Exception as e:
|
|
130
167
|
file_contents[str(file_path)] = f"<error reading file: {e}>"
|
|
131
|
-
if not ctx.obj.get("quiet"):
|
|
132
|
-
console.print(f"[warning]
|
|
168
|
+
if ctx.obj.get("verbose") and not ctx.obj.get("quiet"):
|
|
169
|
+
console.print(f"[warning]Debug snapshot: Error reading {file_path}: {e}[/warning]")
|
|
133
170
|
|
|
134
171
|
payload: Dict[str, Any] = {
|
|
135
172
|
"schema_version": 1,
|
|
@@ -166,15 +203,26 @@ def _write_core_dump(
|
|
|
166
203
|
|
|
167
204
|
dump_path.write_text(json.dumps(payload, indent=2), encoding="utf-8")
|
|
168
205
|
|
|
206
|
+
# Garbage collect old core dumps after writing (Issue #231)
|
|
207
|
+
# This ensures we keep at most N dumps, not N+1
|
|
208
|
+
keep_core_dumps = ctx.obj.get("keep_core_dumps", 10)
|
|
209
|
+
garbage_collect_core_dumps(keep=keep_core_dumps)
|
|
210
|
+
|
|
169
211
|
if not ctx.obj.get("quiet"):
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
212
|
+
# Check if the dump still exists after GC (may be deleted if keep=0)
|
|
213
|
+
if dump_path.exists():
|
|
214
|
+
console.print(
|
|
215
|
+
f"[info]📦 Debug snapshot saved to [path]{dump_path}[/path] "
|
|
216
|
+
"(attach when reporting bugs)[/info]"
|
|
217
|
+
)
|
|
218
|
+
else:
|
|
219
|
+
console.print(
|
|
220
|
+
"[info]📦 Debug snapshot saved and immediately cleaned up (--keep-core-dumps=0)[/info]"
|
|
221
|
+
)
|
|
174
222
|
except Exception as exc:
|
|
175
|
-
# Never let
|
|
223
|
+
# Never let debug snapshot creation crash the CLI
|
|
176
224
|
if not ctx.obj.get("quiet"):
|
|
177
|
-
console.print(f"[warning]Failed to write
|
|
225
|
+
console.print(f"[warning]Failed to write debug snapshot: {exc}[/warning]", style="warning")
|
|
178
226
|
|
|
179
227
|
|
|
180
228
|
def _get_github_token() -> Optional[str]:
|
pdd/fix_main.py
CHANGED
|
@@ -417,8 +417,10 @@ def fix_main(
|
|
|
417
417
|
rprint(f"[bold red]Error printing analysis preview: {e}[/bold red]")
|
|
418
418
|
if success:
|
|
419
419
|
rprint("[bold green]Fixed files saved:[/bold green]")
|
|
420
|
-
|
|
421
|
-
|
|
420
|
+
if fixed_unit_test:
|
|
421
|
+
rprint(f" Test file: {output_file_paths['output_test']}")
|
|
422
|
+
if fixed_code:
|
|
423
|
+
rprint(f" Code file: {output_file_paths['output_code']}")
|
|
422
424
|
if output_file_paths.get("output_results"):
|
|
423
425
|
rprint(f" Results file: {output_file_paths['output_results']}")
|
|
424
426
|
|