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.
Files changed (39) hide show
  1. pdd/__init__.py +1 -1
  2. pdd/agentic_bug_orchestrator.py +15 -6
  3. pdd/agentic_change_orchestrator.py +18 -7
  4. pdd/agentic_common.py +68 -40
  5. pdd/agentic_crash.py +2 -1
  6. pdd/agentic_e2e_fix_orchestrator.py +165 -9
  7. pdd/agentic_update.py +2 -1
  8. pdd/agentic_verify.py +3 -2
  9. pdd/auto_include.py +51 -0
  10. pdd/commands/analysis.py +32 -25
  11. pdd/commands/connect.py +69 -1
  12. pdd/commands/fix.py +31 -13
  13. pdd/commands/generate.py +5 -0
  14. pdd/commands/modify.py +47 -11
  15. pdd/commands/utility.py +12 -7
  16. pdd/core/cli.py +17 -4
  17. pdd/core/dump.py +68 -20
  18. pdd/fix_main.py +4 -2
  19. pdd/frontend/dist/assets/index-CUWd8al1.js +450 -0
  20. pdd/frontend/dist/index.html +1 -1
  21. pdd/llm_invoke.py +82 -12
  22. pdd/operation_log.py +342 -0
  23. pdd/postprocess.py +122 -100
  24. pdd/prompts/agentic_change_step12_create_pr_LLM.prompt +11 -2
  25. pdd/prompts/generate_test_LLM.prompt +0 -1
  26. pdd/prompts/generate_test_from_example_LLM.prompt +251 -0
  27. pdd/prompts/prompt_code_diff_LLM.prompt +29 -25
  28. pdd/server/routes/prompts.py +26 -1
  29. pdd/server/terminal_spawner.py +15 -7
  30. pdd/sync_orchestration.py +164 -147
  31. pdd/sync_order.py +304 -0
  32. pdd/update_main.py +48 -24
  33. {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/METADATA +3 -3
  34. {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/RECORD +37 -35
  35. pdd/frontend/dist/assets/index-DQ3wkeQ2.js +0 -449
  36. {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/WHEEL +0 -0
  37. {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/entry_points.txt +0 -0
  38. {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/licenses/LICENSE +0 -0
  39. {pdd_cli-0.0.118.dist-info → pdd_cli-0.0.121.dist-info}/top_level.txt +0 -0
pdd/sync_order.py ADDED
@@ -0,0 +1,304 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import re
5
+ import stat
6
+ import logging
7
+ from datetime import datetime
8
+ from pathlib import Path
9
+ from typing import Set, Optional, Dict, List, Tuple, Deque
10
+ from collections import deque, defaultdict
11
+
12
+ from rich.console import Console
13
+
14
+ # Initialize rich console
15
+ console = Console()
16
+
17
+ # Configure logging
18
+ logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
19
+ logger = logging.getLogger(__name__)
20
+
21
+ def extract_includes_from_file(file_path: Path) -> Set[str]:
22
+ """
23
+ Parses <include> tags from a prompt file.
24
+
25
+ Args:
26
+ file_path: Path to the prompt file.
27
+
28
+ Returns:
29
+ Set of included paths found in the file. Returns empty set if file
30
+ cannot be read.
31
+ """
32
+ if not file_path.exists() or not file_path.is_file():
33
+ logger.warning(f"File not found or not a file: {file_path}")
34
+ return set()
35
+
36
+ try:
37
+ content = file_path.read_text(encoding="utf-8")
38
+ # Regex pattern matching <include>...</include> tags
39
+ pattern = r'<include>(.*?)</include>'
40
+ matches = re.findall(pattern, content, re.DOTALL)
41
+
42
+ # Clean up matches (strip whitespace)
43
+ includes = {m.strip() for m in matches if m.strip()}
44
+ return includes
45
+ except Exception as e:
46
+ logger.error(f"Error reading file {file_path}: {e}")
47
+ return set()
48
+
49
+
50
+ def extract_module_from_include(include_path: str) -> Optional[str]:
51
+ """
52
+ Maps include paths to module names by stripping suffixes.
53
+
54
+ Args:
55
+ include_path: The path string found inside an include tag.
56
+
57
+ Returns:
58
+ The extracted module name, or None if it's not a module include.
59
+ """
60
+ path_obj = Path(include_path)
61
+ filename = path_obj.name
62
+ stem = path_obj.stem
63
+
64
+ # Logic:
65
+ # 1. If it's a context example file (e.g., context/llm_invoke_example.py)
66
+ # 2. If it's a prompt file with language suffix (e.g., prompts/cli_python.prompt)
67
+
68
+ # Check if it looks like a module file:
69
+ # - Example files contain "_example" in the stem
70
+ # - Prompt files must have a language suffix (_python, _typescript, _LLM)
71
+ is_example = "_example" in stem
72
+ has_language_suffix = bool(re.search(r'(_python|_typescript|_LLM)$', stem, re.IGNORECASE))
73
+ is_module_prompt = filename.endswith(".prompt") and has_language_suffix
74
+
75
+ if not (is_example or is_module_prompt):
76
+ return None
77
+
78
+ # Remove suffixes
79
+ # Order matters: remove language specific suffixes first, then _example
80
+ clean_name = stem
81
+
82
+ # Remove language suffixes
83
+ clean_name = re.sub(r'(_python|_typescript|_LLM)$', '', clean_name, flags=re.IGNORECASE)
84
+
85
+ # Remove example suffix
86
+ clean_name = re.sub(r'_example$', '', clean_name, flags=re.IGNORECASE)
87
+
88
+ if not clean_name:
89
+ return None
90
+
91
+ return clean_name
92
+
93
+
94
+ def build_dependency_graph(prompts_dir: Path) -> Dict[str, List[str]]:
95
+ """
96
+ Scans prompt files and builds a dependency graph based on includes.
97
+
98
+ Args:
99
+ prompts_dir: Directory containing .prompt files.
100
+
101
+ Returns:
102
+ Dictionary mapping module_name -> list of dependencies (modules it depends on).
103
+ """
104
+ if not prompts_dir.exists() or not prompts_dir.is_dir():
105
+ logger.error(f"Prompts directory not found: {prompts_dir}")
106
+ return {}
107
+
108
+ dependency_graph: Dict[str, Set[str]] = defaultdict(set)
109
+
110
+ # Scan for relevant prompt files
111
+ patterns = ["*_python.prompt", "*_typescript.prompt", "*_LLM.prompt"]
112
+ prompt_files: List[Path] = []
113
+ for pattern in patterns:
114
+ prompt_files.extend(prompts_dir.glob(pattern))
115
+
116
+ for p_file in prompt_files:
117
+ # Determine current module name from filename
118
+ # e.g., "foo_python.prompt" -> "foo"
119
+ current_module = extract_module_from_include(p_file.name)
120
+
121
+ if not current_module:
122
+ continue
123
+
124
+ # Ensure module exists in graph even if it has no dependencies
125
+ if current_module not in dependency_graph:
126
+ dependency_graph[current_module] = set()
127
+
128
+ # Parse includes
129
+ includes = extract_includes_from_file(p_file)
130
+
131
+ for inc in includes:
132
+ dep_module = extract_module_from_include(inc)
133
+
134
+ # Add dependency if valid and not self-reference
135
+ if dep_module and dep_module != current_module:
136
+ dependency_graph[current_module].add(dep_module)
137
+
138
+ # Convert sets to lists for return type consistency
139
+ return {k: list(v) for k, v in dependency_graph.items()}
140
+
141
+
142
+ def topological_sort(graph: Dict[str, List[str]]) -> Tuple[List[str], List[List[str]]]:
143
+ """
144
+ Performs topological sort using Kahn's algorithm.
145
+
146
+ Args:
147
+ graph: Adjacency list (module -> dependencies).
148
+
149
+ Returns:
150
+ Tuple containing:
151
+ 1. List of modules in topological order (dependencies first).
152
+ 2. List of cycles detected (if any).
153
+ """
154
+ # Calculate in-degrees (number of modules depending on key)
155
+ # Note: The input graph is "Module -> Depends On".
156
+ # For Kahn's algo to output [Dependency, ..., Dependent], we need to process
157
+ # nodes with 0 dependencies first.
158
+
159
+ # Normalize graph to ensure all nodes are keys
160
+ all_nodes = set(graph.keys())
161
+ for deps in graph.values():
162
+ all_nodes.update(deps)
163
+
164
+ adj_list = {node: graph.get(node, []) for node in all_nodes}
165
+
166
+ # In Kahn's, usually we track edges: Dependency -> Dependent.
167
+ # Our input is Dependent -> [Dependencies].
168
+ # So, in-degree here represents "number of unsatisfied dependencies".
169
+ in_degree = {node: 0 for node in all_nodes}
170
+
171
+ # Reverse graph: Dependency -> [Dependents] (needed to update neighbors)
172
+ reverse_graph: Dict[str, List[str]] = defaultdict(list)
173
+
174
+ for node, deps in adj_list.items():
175
+ in_degree[node] = len(deps)
176
+ for dep in deps:
177
+ reverse_graph[dep].append(node)
178
+
179
+ # Queue for nodes with 0 dependencies
180
+ queue: Deque[str] = deque([node for node, deg in in_degree.items() if deg == 0])
181
+
182
+ sorted_list: List[str] = []
183
+ processed_count = 0
184
+
185
+ while queue:
186
+ u = queue.popleft()
187
+ sorted_list.append(u)
188
+ processed_count += 1
189
+
190
+ # For every module 'v' that depends on 'u'
191
+ for v in reverse_graph[u]:
192
+ in_degree[v] -= 1
193
+ if in_degree[v] == 0:
194
+ queue.append(v)
195
+
196
+ cycles: List[List[str]] = []
197
+
198
+ if processed_count != len(all_nodes):
199
+ # Cycle detected. Identify nodes involved in cycles.
200
+ remaining_nodes = [n for n, deg in in_degree.items() if deg > 0]
201
+ if remaining_nodes:
202
+ cycles.append(remaining_nodes)
203
+ logger.warning(f"Cyclic dependencies detected involving: {remaining_nodes}")
204
+
205
+ return sorted_list, cycles
206
+
207
+
208
+ def get_affected_modules(sorted_modules: List[str], modified: Set[str], graph: Dict[str, List[str]]) -> List[str]:
209
+ """
210
+ Identifies modules that need syncing based on modified modules and dependencies.
211
+
212
+ Args:
213
+ sorted_modules: Full list of modules in topological order.
214
+ modified: Set of module names that have changed.
215
+ graph: Dependency graph (module -> dependencies).
216
+
217
+ Returns:
218
+ List of modules to sync, preserving topological order.
219
+ """
220
+ if not modified:
221
+ return []
222
+
223
+ # Build reverse graph: Dependency -> [Dependents]
224
+ # This allows us to traverse "up" the chain from a modified dependency to things that use it
225
+ reverse_graph: Dict[str, Set[str]] = defaultdict(set)
226
+ for node, deps in graph.items():
227
+ for dep in deps:
228
+ reverse_graph[dep].add(node)
229
+
230
+ affected = set()
231
+ queue = deque(modified)
232
+
233
+ # BFS to find all transitive dependents
234
+ while queue:
235
+ current = queue.popleft()
236
+ if current in affected:
237
+ continue
238
+
239
+ affected.add(current)
240
+
241
+ # Add all modules that depend on current
242
+ for dependent in reverse_graph.get(current, []):
243
+ if dependent not in affected:
244
+ queue.append(dependent)
245
+
246
+ # Filter sorted_modules to keep only affected ones, preserving order
247
+ result = [m for m in sorted_modules if m in affected]
248
+
249
+ return result
250
+
251
+
252
+ def generate_sync_order_script(modules: List[str], output_path: Path, worktree_path: Optional[Path] = None) -> str:
253
+ """
254
+ Generates a shell script to execute pdd sync commands in order.
255
+
256
+ Args:
257
+ modules: Ordered list of module names to sync.
258
+ output_path: Path where the script should be written.
259
+ worktree_path: Optional path to cd into before running commands.
260
+
261
+ Returns:
262
+ The content of the generated script.
263
+ """
264
+ if not modules:
265
+ logger.info("No modules to sync. Skipping script generation.")
266
+ return ""
267
+
268
+ lines = [
269
+ "#!/bin/bash",
270
+ "#",
271
+ "# PDD Sync Order Script",
272
+ f"# Generated: {datetime.now().isoformat()}",
273
+ f"# Total Modules: {len(modules)}",
274
+ "#",
275
+ "",
276
+ "set -e # Exit immediately if a command exits with a non-zero status",
277
+ ""
278
+ ]
279
+
280
+ if worktree_path:
281
+ lines.append(f"cd {worktree_path}")
282
+ lines.append("")
283
+
284
+ total = len(modules)
285
+ for i, module in enumerate(modules, 1):
286
+ lines.append(f'echo "[{i}/{total}] Syncing {module}..."')
287
+ lines.append(f"pdd sync {module}")
288
+ lines.append("")
289
+
290
+ script_content = "\n".join(lines)
291
+
292
+ try:
293
+ output_path.write_text(script_content, encoding="utf-8")
294
+
295
+ # Make executable (chmod +x)
296
+ st = os.stat(output_path)
297
+ os.chmod(output_path, st.st_mode | stat.S_IEXEC)
298
+
299
+ console.print(f"[green]Successfully generated sync script at: {output_path}[/green]")
300
+ except Exception as e:
301
+ console.print(f"[red]Failed to write sync script: {e}[/red]")
302
+ raise
303
+
304
+ return script_content
pdd/update_main.py CHANGED
@@ -38,6 +38,7 @@ def resolve_prompt_code_pair(code_file_path: str, quiet: bool = False, output_di
38
38
  Derives the corresponding prompt file path from a code file path.
39
39
  Searches for and creates prompts only in the specified output directory or 'prompts' directory.
40
40
  If the prompt file does not exist, it creates an empty one in the target directory.
41
+ Preserves the subdirectory structure of the code file relative to the repository root.
41
42
 
42
43
  Args:
43
44
  code_file_path: Path to the code file
@@ -50,48 +51,71 @@ def resolve_prompt_code_pair(code_file_path: str, quiet: bool = False, output_di
50
51
  # Extract the filename without extension and directory
51
52
  code_filename = os.path.basename(code_file_path)
52
53
  base_name, _ = os.path.splitext(code_filename)
54
+
55
+ code_file_abs_path = os.path.abspath(code_file_path)
56
+ code_dir = os.path.dirname(code_file_abs_path)
53
57
 
54
- # Determine the output directory
58
+ # Find the repository root (where the code file is located)
59
+ # This is needed for relative path calculation to preserve structure
60
+ repo_root = code_dir
61
+ try:
62
+ import git
63
+ repo = git.Repo(code_dir, search_parent_directories=True)
64
+ repo_root = repo.working_tree_dir
65
+ except:
66
+ # If not a git repo, use the directory containing the code file
67
+ pass
68
+
69
+ # Determine the base prompts directory
55
70
  if output_dir:
56
71
  # Use the custom output directory (absolute path)
57
- prompts_dir = os.path.abspath(output_dir)
72
+ base_prompts_dir = os.path.abspath(output_dir)
58
73
  else:
59
- # Find the repository root (where the code file is located)
60
- code_file_abs_path = os.path.abspath(code_file_path)
61
- code_dir = os.path.dirname(code_file_abs_path)
62
-
63
- # For repository mode, find the actual repo root
64
- repo_root = code_dir
65
- try:
66
- import git
67
- repo = git.Repo(code_dir, search_parent_directories=True)
68
- repo_root = repo.working_tree_dir
69
- except:
70
- # If not a git repo, use the directory containing the code file
71
- pass
72
-
73
74
  # Use context-aware prompts_dir from .pddrc if available
74
75
  context_name, context_config = detect_context_for_file(code_file_path, repo_root)
75
76
  prompts_dir_config = context_config.get("prompts_dir", "prompts")
76
77
  if os.path.isabs(prompts_dir_config):
77
- prompts_dir = prompts_dir_config
78
+ base_prompts_dir = prompts_dir_config
78
79
  else:
79
- prompts_dir = os.path.join(repo_root, prompts_dir_config)
80
+ base_prompts_dir = os.path.join(repo_root, prompts_dir_config)
81
+
82
+ # Calculate relative path from repo_root to code_dir to preserve structure
83
+ try:
84
+ rel_dir = os.path.relpath(code_dir, repo_root)
85
+ if rel_dir == ".":
86
+ rel_dir = ""
87
+ else:
88
+ # If context has a code root (generate_output_path), strip that prefix
89
+ # E.g., for pdd/commands/file.py with generate_output_path="pdd",
90
+ # strip "pdd/" to get "commands/"
91
+ code_root = context_config.get("generate_output_path", "")
92
+ if code_root and rel_dir.startswith(code_root + os.sep):
93
+ # Strip the code root prefix
94
+ rel_dir = rel_dir[len(code_root) + len(os.sep):]
95
+ elif code_root and rel_dir == code_root:
96
+ # File is directly in code root
97
+ rel_dir = ""
98
+ except ValueError:
99
+ # Can happen on Windows if paths are on different drives
100
+ rel_dir = ""
101
+
102
+ # Construct the final directory including the relative structure
103
+ final_prompts_dir = os.path.join(base_prompts_dir, rel_dir)
80
104
 
81
105
  # Construct the prompt filename in the determined directory
82
106
  prompt_filename = f"{base_name}_{language}.prompt"
83
- prompt_path_str = os.path.join(prompts_dir, prompt_filename)
107
+ prompt_path_str = os.path.join(final_prompts_dir, prompt_filename)
84
108
  prompt_path = Path(prompt_path_str)
85
109
 
86
110
  # Ensure prompts directory exists
87
- prompts_path = Path(prompts_dir)
111
+ prompts_path = Path(final_prompts_dir)
88
112
  if not prompts_path.exists():
89
113
  try:
90
114
  prompts_path.mkdir(parents=True, exist_ok=True)
91
115
  if not quiet:
92
- console.print(f"[success]Created prompts directory:[/success] [path]{prompts_dir}[/path]")
116
+ console.print(f"[success]Created prompts directory:[/success] [path]{final_prompts_dir}[/path]")
93
117
  except OSError as e:
94
- console.print(f"[error]Failed to create prompts directory {prompts_dir}: {e}[/error]")
118
+ console.print(f"[error]Failed to create prompts directory {final_prompts_dir}: {e}[/error]")
95
119
 
96
120
  if not prompt_path.exists():
97
121
  try:
@@ -222,7 +246,7 @@ def update_file_pair(prompt_file: str, code_file: str, ctx: click.Context, repo:
222
246
  temperature=ctx.obj.get("temperature", 0),
223
247
  verbose=verbose,
224
248
  time=ctx.obj.get('time', DEFAULT_TIME),
225
- simple=True, # Force legacy since we already tried agentic
249
+ simple=True, # Force legacy since we already tried agentic,
226
250
  quiet=quiet,
227
251
  prompt_file=prompt_file,
228
252
  )
@@ -601,4 +625,4 @@ def update_main(
601
625
  if not quiet:
602
626
  rprint(f"[bold red]Error:[/bold red] {str(e)}")
603
627
  # Return error result instead of sys.exit(1) to allow orchestrator to handle gracefully
604
- return None
628
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pdd-cli
3
- Version: 0.0.118
3
+ Version: 0.0.121
4
4
  Summary: PDD (Prompt-Driven Development) Command Line Interface
5
5
  Author: Greg Tanaka
6
6
  Author-email: glt@alumni.caltech.edu
@@ -64,7 +64,7 @@ Requires-Dist: twine; extra == "dev"
64
64
  Requires-Dist: httpx==0.28.1; extra == "dev"
65
65
  Dynamic: license-file
66
66
 
67
- .. image:: https://img.shields.io/badge/pdd--cli-v0.0.118-blue
67
+ .. image:: https://img.shields.io/badge/pdd--cli-v0.0.121-blue
68
68
  :alt: PDD-CLI Version
69
69
 
70
70
  .. image:: https://img.shields.io/badge/Discord-join%20chat-7289DA.svg?logo=discord&logoColor=white&link=https://discord.gg/Yp4RTh8bG7
@@ -141,7 +141,7 @@ After installation, verify:
141
141
 
142
142
  pdd --version
143
143
 
144
- You'll see the current PDD version (e.g., 0.0.118).
144
+ You'll see the current PDD version (e.g., 0.0.121).
145
145
 
146
146
  Getting Started with Examples
147
147
  -----------------------------
@@ -1,20 +1,20 @@
1
- pdd/__init__.py,sha256=b4-LQ8M8-GunClwSNK3e2ylVg3JSiuBWMjkqK7fTlOw,1893
1
+ pdd/__init__.py,sha256=8rLvde1g1_pXcJeRVEG1DPAriLyzlgL0qre21-7yoWg,1893
2
2
  pdd/agentic_bug.py,sha256=ujaV29jbfMrD8BAcGcQUrkSLG5jCW-oPBk_Aw3LPMYU,11004
3
- pdd/agentic_bug_orchestrator.py,sha256=0zIBrlvMyz5AW7EnDVeF_Wil89XhpAUwxebThVm8aCI,18808
3
+ pdd/agentic_bug_orchestrator.py,sha256=ODUA6u-Nr_Hwzlug0ziY1JuDdfAwpksQO6uB-GfwWj0,19357
4
4
  pdd/agentic_change.py,sha256=9Ydq6l-yDKhRJGiwcy6LbTRKGxyagnsRpmlE8auQ2io,7307
5
- pdd/agentic_change_orchestrator.py,sha256=7dDpaYCA0n3pfvU2zlNgz240BxxyFS9LaoXiZlcDFGY,20808
6
- pdd/agentic_common.py,sha256=1ccBQQkrxQB-SreJyGMhl3zrdi3m-9djG_dTgmqXmPY,18940
7
- pdd/agentic_crash.py,sha256=kmpcvf0Yi8tutWq8fcXZAT0CC1_Fga1F_IApJKhmLGo,17710
5
+ pdd/agentic_change_orchestrator.py,sha256=p9_L7vD8bB8DRj8nHYCF4mJ_50h_co4hyWVrzFYt0hM,21395
6
+ pdd/agentic_common.py,sha256=Aub4sXlvNVRrauYdbl0PcHeTq36iAcQUfsqOcHgd_dU,20160
7
+ pdd/agentic_crash.py,sha256=A9_tnMidCb-pvGGRiVKr7Hj8CwHJ4h3e9TN87a1kh8E,17776
8
8
  pdd/agentic_e2e_fix.py,sha256=LS30pp4pGN-6MkpEVGnkHLGVpGWLcRvGdVFrgLUwkNE,10815
9
- pdd/agentic_e2e_fix_orchestrator.py,sha256=Wn6j5ur1bHzwC5YhNUpiFM_71sR2HS06Mfr2IWWRxWI,17151
9
+ pdd/agentic_e2e_fix_orchestrator.py,sha256=HUGEXA8uKXvxSG0J2qsEutJV_bZJlnhTCdNCS-NXyoU,22423
10
10
  pdd/agentic_fix.py,sha256=w9WKoxCeaH78NpA6B6zCwS_fpRtF3jyadqFfiu4_row,53288
11
11
  pdd/agentic_langtest.py,sha256=BOiyIJTOf7lBEZscG9e0XSu4Sp7NiMGgkquATcw7eMc,6326
12
- pdd/agentic_update.py,sha256=8FbZi__4y6l4Smn3S6P4NOQvbdfOxyb6YJtwLr3j5LY,13392
13
- pdd/agentic_verify.py,sha256=o86BgoXLnDo1p9N1sKH4Vu7bieRI5W51cMNfnMXW3e0,6412
12
+ pdd/agentic_update.py,sha256=RM3F3x8ASr1fuIkTdonuAtUxo8P3O-ckgz3RKZk8qb8,13458
13
+ pdd/agentic_verify.py,sha256=vZCNjcv-y2TiI6XmuA__fOKYNLzKPLrCHRYYrMZyUHU,6475
14
14
  pdd/architecture_sync.py,sha256=MBSwyajOn50RcBAKBLZNx4133UHTPMwxvv7w1DcIDJg,19061
15
15
  pdd/auth_service.py,sha256=kup_TkldSAkfXofJ_-UPqMQiFIopCATgz-iYkrFBQRg,5999
16
16
  pdd/auto_deps_main.py,sha256=AHuAQFvO6Xn8e1vVwiW5VUIvE4H6cSbjmIv3UU5x62Y,5017
17
- pdd/auto_include.py,sha256=UgvWV0ZbwSjWkgn9tl9LpayXXPnSFcRzbDR8rjFgeOk,16745
17
+ pdd/auto_include.py,sha256=YJqU-nFm2M7cmHUU66Jqj8bj1Z6fvbMQNxH_Lqd5tDo,18666
18
18
  pdd/auto_update.py,sha256=CUXEipFsJ4NwHFqsjafi8DPEosCTnxy5baswvbOerbo,8310
19
19
  pdd/bug_main.py,sha256=-mSQmjj89MAucYqNur9pjOgp2ZnIp2IgpQrZPp0SDas,13267
20
20
  pdd/bug_to_unit_test.py,sha256=BoQqNyKQpBQDW8-JwBH_RX4RHRSiU8Kk3EplFrkECt0,6665
@@ -41,7 +41,7 @@ pdd/fix_code_loop.py,sha256=1hWPKJmVwsEFA0cbcgChyJL0yAMQ7Cw2_TdXpO1Y82o,40526
41
41
  pdd/fix_code_module_errors.py,sha256=zbWxaBzAYp9r0owZvlN46aAFKA1gZyOjZqX6vCEz7Yk,5579
42
42
  pdd/fix_error_loop.py,sha256=g3lCi737o69Z6aUp9zJnNDCnG9Zx5JdAJPgcHfv_JzI,43300
43
43
  pdd/fix_errors_from_unit_tests.py,sha256=00vanOVvZ8KUvQMaUtAoComjZNwiyrXd3bvi8iCUCXk,9577
44
- pdd/fix_main.py,sha256=XW3pnoDHqD0Zjgwzg2BrxgxV6hIY41702si25L9jxmo,27932
44
+ pdd/fix_main.py,sha256=ZUwmF16YiIJix3gPc1AcI7lGsfgV0lDYB7Kmb5XtTb4,28007
45
45
  pdd/fix_verification_errors.py,sha256=oT0edNBj4CTd1kaE0vdnWjyB6el1tECh0sIOZ8O1AmQ,11583
46
46
  pdd/fix_verification_errors_loop.py,sha256=9R_hEHWf4PWAUFdP5rZl0fzdDH9d3jjvprf9vhhnpnY,68169
47
47
  pdd/fix_verification_main.py,sha256=Q9OP-ToZ1Qv4nsRICDJQ0_NtF4hO4fs-w2j0Kxr6xPo,35790
@@ -58,15 +58,16 @@ pdd/increase_tests.py,sha256=68cM9d1CpaLLm2ISFpJw39xbRjsfwxwS06yAwRoUCHk,4433
58
58
  pdd/incremental_code_generator.py,sha256=RoaJDavR0A5ybXc8Pvqe7Hwwhz9gHbP_kmGQXn3XveQ,9425
59
59
  pdd/insert_includes.py,sha256=wPRYeWl2IxMNtqsANeeUdZo3CR4h2bo8-d5nYWsnGg0,6104
60
60
  pdd/install_completion.py,sha256=bLMJuMOBDvsEnDAUpgiPesNRGhY_IvBvz8ZvmbTzP4o,5472
61
- pdd/llm_invoke.py,sha256=5pZyHOA18nScOdxZCit4GyJ4hFxWWEhZV2Q-2zFTDwM,147589
61
+ pdd/llm_invoke.py,sha256=kyOcK0HMT8fk5zRAlj6QSL9skLFAJX7JSUIZEhJT9Es,150324
62
62
  pdd/load_prompt_template.py,sha256=A4CwhRCu4G1OPisZK-ZkdafjqTWGshxvxPm-czi7Als,2287
63
63
  pdd/logo_animation.py,sha256=n6HJWzuFze2csAAW2-zbxfjvWFYRI4hIdwVBtHBOkj4,20782
64
64
  pdd/mcp_config.json,sha256=D3ctWHlShvltbtH37zbYb6smVE0V80_lGjDKDIqsSBE,124
65
+ pdd/operation_log.py,sha256=E7e4R7OLHVVYqGTd25rJSEDPtWAnBqzYhxdtd4-NaE4,10859
65
66
  pdd/path_resolution.py,sha256=TFEzlc2W_x_jwBwB5uTC3jYXMy9v-HyDkQg_DCbUHXU,4180
66
67
  pdd/pdd_completion.fish,sha256=pfEyBWzFp3matC_SW2BTDNaBJybYKUEi3YpPE-D6AKU,13776
67
68
  pdd/pdd_completion.sh,sha256=xgx-g6aeCCrlh6loeLyJN5jCsX15YXrWyT1U499p3C0,6490
68
69
  pdd/pdd_completion.zsh,sha256=V9-V8jqw3osjlXNOvjYMJf0E771-_EQe-Cboo1xzPvY,17090
69
- pdd/postprocess.py,sha256=BU2xaWLGWHb2Wpea4X5BL3oUQmiKHCBzKD1yoSmjfis,5061
70
+ pdd/postprocess.py,sha256=jS6TG0FaH48qSVI7MoIsd6uXsc3Xmmzgu29AP2k2mJM,5936
70
71
  pdd/postprocess_0.py,sha256=OW17GyCFLYErCyWh2tL4syuho3q2yFf2wyekQ4BLdPM,2168
71
72
  pdd/preprocess.py,sha256=4y6HYQPBC6IE66aPWg_Gjyg4dUWbqKQLAQ_qKuP8Y48,22388
72
73
  pdd/preprocess_main.py,sha256=apW_L_s4iaI_UwVV90VhlCe4PvJDijd84kc7Hrx5tlY,4889
@@ -83,7 +84,8 @@ pdd/summarize_directory.py,sha256=TDihusV04mJiHV8X4-IFSs2LhTKlGiMGM7gQkXl4zA4,10
83
84
  pdd/sync_animation.py,sha256=5gFg8G8PKMtJLkScOV98OADyQhLMnw6rJf0pqZxAiQY,28274
84
85
  pdd/sync_determine_operation.py,sha256=dlBu5Qf8aJ22h2VLQ-sfJAvxw2DqpLp2im0SW58PhAY,89907
85
86
  pdd/sync_main.py,sha256=YFIeRO5Jp39VX1GXx-bRoggFRKhK6PVT0qPNn0Iq64Q,27062
86
- pdd/sync_orchestration.py,sha256=n3OhCc5_aQdTukUunyb60QAf5kNDdGsfJaSkEPklC1s,85089
87
+ pdd/sync_orchestration.py,sha256=vnE5Ne3Tkq9Ud7RBK5WS4bfzxlA0AVXGocto1_7DeEY,86841
88
+ pdd/sync_order.py,sha256=Uep8okR_6vL9z4WTeVTNZoaC1s3uzEZjOTd02C-fHRU,9899
87
89
  pdd/sync_tui.py,sha256=gponSnFNHMO9uTRsmJnL5McCgLbeGeAa34d379STthI,29300
88
90
  pdd/template_expander.py,sha256=vKpnDzNLn6dyaqhZBucBJa0s1LfntiqOOfi90GyXXts,4842
89
91
  pdd/template_registry.py,sha256=L8ZQ-apmdDe7Jj_JlgHv7fUoIiJnGDuE0V64Y-MO9vA,8099
@@ -91,27 +93,27 @@ pdd/trace.py,sha256=n_h5gS8d7ywUmVuTmjtlQVkO5op_YrJeVwZKx9ZC-8s,12233
91
93
  pdd/trace_main.py,sha256=SOnMEHta9WaMAxulMrk6aFojma4ti61ILvJp3NVhpbg,4992
92
94
  pdd/track_cost.py,sha256=r1AA0rTm4FR3vdn7TrwNGHnE7MaFqhIlQcgGFIL9gsA,7669
93
95
  pdd/unfinished_prompt.py,sha256=vrzJ5q9VHQChaLLeCXMLCP0QsfWNt1cFnVOhFEN12iU,6333
94
- pdd/update_main.py,sha256=1iivSF3JjSE6bRRjIHB6JsDKRZ6zl6HYbhBH6WivI2E,25839
96
+ pdd/update_main.py,sha256=8Odw5X1RG82uGP0wva5qi7EBIpLPblOdfoHgtlkHhKY,26991
95
97
  pdd/update_model_costs.py,sha256=RfeOlAHtc1FCx47A7CjrH2t5WXQclQ_9uYtNjtQh75I,22998
96
98
  pdd/update_prompt.py,sha256=K1i9BIpb3ioFGM32WcqueAuKqzLlezsPsvcovOagOhI,5239
97
99
  pdd/xml_tagger.py,sha256=5Bc3HRm7iz_XjBdzQIcMb8KocUQ8PELI2NN5Gw4amd4,4825
98
100
  pdd/commands/__init__.py,sha256=5ID0Erk2chGBWPE7f_6vJy3-YE_Fc991DEfU4m8QZSc,1617
99
- pdd/commands/analysis.py,sha256=PM-5lt9kMG6JZ5Z69wOEm2RaDzcHrv9hn6XxCcKXkos,9613
101
+ pdd/commands/analysis.py,sha256=m0zNvyzVinsY3-Fr6bDtRlr-fynRRtQLwdYOymC8HAA,10090
100
102
  pdd/commands/auth.py,sha256=tGULnVN6a7x4rMtVCGUnvcEivRsvYUg4jQS3Koezw1Q,10170
101
- pdd/commands/connect.py,sha256=dWsNV_Nek4hXZMBzC1BJ0-CMet7r6jknaxx2rZxQ09k,10437
102
- pdd/commands/fix.py,sha256=8r4Iudon9kE7DMKIuh9fN4FwV_5nMe9UZbsYIg2BvYo,6964
103
- pdd/commands/generate.py,sha256=RkKvIFqpYmZeJzCgAMGF6abK7CR85g-m_SIXO5lgOyQ,8686
103
+ pdd/commands/connect.py,sha256=dqjWEWw6EcRcK8yJHJEoDuLQocd8UiyBEBqELa_U-J0,13073
104
+ pdd/commands/fix.py,sha256=RWqGaK9GYoQRbzHmQlEBug22hoMLE69hcHsoJC6dFF8,7928
105
+ pdd/commands/generate.py,sha256=Obaxp96yRGgT1d3qkGCJ-wVTbg0ZLTkIgBmjo72kbbs,8940
104
106
  pdd/commands/maintenance.py,sha256=DgAI_nQttdNkSaD9W0mJDtizevy6mKRMkfjlgJwwMes,5025
105
107
  pdd/commands/misc.py,sha256=i9GK0wto-3oleB0tSwcsHipl9Shs2vEZ40-pUrdX0S4,2574
106
- pdd/commands/modify.py,sha256=bTCvX_duAdQWxDe0RSeG4jMpyXV5dKxwm5iNiaXZTnE,9370
108
+ pdd/commands/modify.py,sha256=NKKMSrRJoLfv-xF9XcSxE7oEZDrBkNt46tPHM_o_Nuk,10868
107
109
  pdd/commands/report.py,sha256=E9CCbbux_MP5oGu18M_XQBVaQhYCMsQOUn9KQPEBiSU,5868
108
110
  pdd/commands/sessions.py,sha256=G7SAS6LfaGBM0QZLAF4DumqLEcVRIby0llDFKadS_Qo,10388
109
111
  pdd/commands/templates.py,sha256=pJicUZww2U5nOcQw_tuQK3OQwYK3NRRc81SZ5YLkt_E,8957
110
- pdd/commands/utility.py,sha256=tz9vmYZAvMVRIGUKd2B5808ggOO9i-4Kk3QykRU8j08,3677
112
+ pdd/commands/utility.py,sha256=JmM5VEGno2yB3ixk1sZQ3ENwS33DKU_AjrMOte_rnu4,3969
111
113
  pdd/core/__init__.py,sha256=m5ywJMVb2PhmHbxC1KMA-TYP7Am4Z1rv_DihgOZRCu0,619
112
- pdd/core/cli.py,sha256=sgRYlTulRJcCd9kCeqxRWf6pvjdtpw3SjLxSv9Cdb2Q,21636
114
+ pdd/core/cli.py,sha256=8LWwh7UVz4lC0XHCVXbAMuQ27olrPFBJ9QvRdmlXHL4,22223
113
115
  pdd/core/cloud.py,sha256=WvaGYwGVw41tClAHc1PyJXDN6xIfRowvBL-Z7JQtFKw,8289
114
- pdd/core/dump.py,sha256=AEwRIaVuWn5Aegov9PNSQ9BQfjrVBl1npohce29XKsY,20419
116
+ pdd/core/dump.py,sha256=R31LXgiAl_u6yB0DPWtfjxs7t_aHO1uoDGiJJABvy88,22161
115
117
  pdd/core/errors.py,sha256=CVI1h7p5K9lRTuw-BYxyGfH68NJ8-ZBGqW-KxD-_6MA,2641
116
118
  pdd/core/remote_session.py,sha256=V46Y9jzKzUmvQbfRejFGCi7t_9hkjp_K78VPwX0NP_s,2163
117
119
  pdd/core/utils.py,sha256=e2y-S6OcDbjJw1vdGWwNTDlICPyYy9H-5yfj5nPaAw8,2524
@@ -120,10 +122,10 @@ pdd/data/llm_model.csv,sha256=n42HslQzEGAjuyio_xpkQCAq7hcN5mumsfOhEcEYvME,1813
120
122
  pdd/docs/prompting_guide.md,sha256=DY5VyJZCYIZ1NAvgjOaCx3Bv_hWo4krW4prwYivaUh0,39525
121
123
  pdd/docs/whitepaper_with_benchmarks/data_and_functions/benchmark_analysis.py,sha256=IwvFLrgGLmx3ajF-Z_eQaRowCzyJk_cQxD3wxMkfZQU,23406
122
124
  pdd/docs/whitepaper_with_benchmarks/data_and_functions/creation_compare.py,sha256=0sEVBjJ0yHQWzh4NbbJPmpsIB2iyJlvwU0uRnV12fDE,26558
123
- pdd/frontend/dist/index.html,sha256=4eVXmbzspE-BXXw4BfF4AqC7VzRLAnkL9EoerHFE-co,11856
125
+ pdd/frontend/dist/index.html,sha256=mySCIUsNdoSjs2zlgCTOiXCuPeAaJc3hK6j2xwhUilc,11856
124
126
  pdd/frontend/dist/logo.svg,sha256=7pD_n_dgwPjM2iPBpj2rfPJ9fg1gfebAWOO4PCpum1U,797
125
127
  pdd/frontend/dist/assets/index-B5DZHykP.css,sha256=HLO_vKmG5ANNQg2BEeOD8KYUvV8sL3rH0i2S1Cwe4T0,7322
126
- pdd/frontend/dist/assets/index-DQ3wkeQ2.js,sha256=M9tu7dNTwoZChtVzic8L8gtKwiJhglfxn_Qjr6OSjws,1598213
128
+ pdd/frontend/dist/assets/index-CUWd8al1.js,sha256=8G0_U6UyaHvgB_Oz6tAm3ouosZzcti5clgFWRnbT9EU,1602195
127
129
  pdd/prompts/agentic_bug_step10_pr_LLM.prompt,sha256=NlkzPKoOwy2aMvu36ZyBKkhYf-Ww5EzhAPmmUsP_6PI,5478
128
130
  pdd/prompts/agentic_bug_step1_duplicate_LLM.prompt,sha256=UQnvHbMF-aN35Pgs2-Eu9VnZdwZmrUpJlkg4bJ4PuEk,2259
129
131
  pdd/prompts/agentic_bug_step2_docs_LLM.prompt,sha256=rFyXFFm9o4BFJDlAcP0iDBRZdDKJI9bCcPoLZ6ZKalk,4110
@@ -136,7 +138,7 @@ pdd/prompts/agentic_bug_step8_verify_LLM.prompt,sha256=iV5q88rdQhMeqI2H6mM6I9ye5
136
138
  pdd/prompts/agentic_bug_step9_e2e_test_LLM.prompt,sha256=zcZTESxyOFg_Ze7ulSf3tIyuUocMAvNwljheslMkEnA,10507
137
139
  pdd/prompts/agentic_change_step10_identify_issues_LLM.prompt,sha256=pzl3-TUy4jC2CaQj9ks-We9ULS09GmORHSrXENXq2dQ,4216
138
140
  pdd/prompts/agentic_change_step11_fix_issues_LLM.prompt,sha256=ou6S1IO7dNZoeTtylpq7VJ5P5_ce7kmtuWR95puvBOI,3226
139
- pdd/prompts/agentic_change_step12_create_pr_LLM.prompt,sha256=dTQpf5iNdvI1hSx_AKcBlGxI63-Pn7kHtxt5AJR-eGY,3069
141
+ pdd/prompts/agentic_change_step12_create_pr_LLM.prompt,sha256=coqLstnZFspnZW0EYcTb8JbdzcjdYXtuI3eyJpf4fXU,3259
140
142
  pdd/prompts/agentic_change_step1_duplicate_LLM.prompt,sha256=22ylrCC1EViSznnjTrRi7n0as-bFarguEPsgiE8K9ow,2305
141
143
  pdd/prompts/agentic_change_step2_docs_LLM.prompt,sha256=fnWGYxz6seWzOtU3SIJsawf_iMP6TX0dkGu_G2vDC_A,3048
142
144
  pdd/prompts/agentic_change_step3_research_LLM.prompt,sha256=MPH0Mt7V1Hmlaa1JU3CK3mCLQ-EmpuYgQJGEwv5mh_A,3771
@@ -185,11 +187,11 @@ pdd/prompts/find_verification_errors_LLM.prompt,sha256=TAvwpsj8RYv6pmmxJK330rGxC
185
187
  pdd/prompts/fix_code_module_errors_LLM.prompt,sha256=VSO0q3KtPbSWZkiJnmpgviUtSu73jpd2u3DWRVp-VbA,3794
186
188
  pdd/prompts/fix_errors_from_unit_tests_LLM.prompt,sha256=3XGMGkBh5jUSXyuafpUsHGE_ynIfCUErAJ3HIkClxlY,5861
187
189
  pdd/prompts/fix_verification_errors_LLM.prompt,sha256=AO1yhxNfM7s-93ZjufGrJUcRvSl04CmZl_WEbnTUFbY,4997
188
- pdd/prompts/generate_test_LLM.prompt,sha256=XsMTzh-mXTiy3LrKucR7ruwZLoILZcyfSWXssLphXJA,4667
190
+ pdd/prompts/generate_test_LLM.prompt,sha256=GE_MNQKyZx4R9AWNIU9TOa2ayFINif7S8N4FHRt4bQ0,4612
189
191
  pdd/prompts/generate_test_from_example_LLM.prompt,sha256=XdMK2KgWRHNm-ph3CxtqeUNz0geCOMt87Qgc6P5dWj4,3678
190
192
  pdd/prompts/increase_tests_LLM.prompt,sha256=XvzvwTyAaxbJIWwUk0iby2CoTfRCVRWbjT3D3G29OYQ,914
191
193
  pdd/prompts/insert_includes_LLM.prompt,sha256=g-p2gXKENsqvfK5Q9FYbqFsIJ5CP7rbxmd4rROA-W80,1453
192
- pdd/prompts/prompt_code_diff_LLM.prompt,sha256=8rf-40BK9kuZ-pQd2FnjCWVlB04bEGVFKcHDM9TcuTQ,5632
194
+ pdd/prompts/prompt_code_diff_LLM.prompt,sha256=_yulkWstjkBUhBjPpoXcXeWXJfobJfsR_fRrGCbHNFM,5831
193
195
  pdd/prompts/prompt_diff_LLM.prompt,sha256=qYI96mZI_8fqf7Iuw_iOxi9HF7XekM7UsV2cUDqttws,2979
194
196
  pdd/prompts/split_LLM.prompt,sha256=cMVyazsue6eerOPYeueqpSNRiITy1ht0HgGytPFiQIk,6244
195
197
  pdd/prompts/summarize_file_LLM.prompt,sha256=qb9K61XMVFy7hgGITglI37Xg7yLPAGQBm0rUBEqRnEc,387
@@ -207,7 +209,7 @@ pdd/server/executor.py,sha256=JJUE_JoAYJBi0vhGr2ZSJbBR9FURXe4K9iYySjp7mak,10563
207
209
  pdd/server/jobs.py,sha256=oLI1luuuR2AFRzsn8b77xGX2ykohHcFbzkY0P9dhBTg,24580
208
210
  pdd/server/models.py,sha256=oXsvCQM7L-cGP0hKLvtZGE98svuoIu4lYFqTu-WQWUE,10530
209
211
  pdd/server/security.py,sha256=XmT4qnRtlkL0KMWTZuzxx0PQ_XdgasYLXYGH2oc3NY4,8746
210
- pdd/server/terminal_spawner.py,sha256=dUQ-h0C3zkSHJ09q4XA1eCxmlpgssDnIBZ5RLAM_100,7655
212
+ pdd/server/terminal_spawner.py,sha256=ULn9ylYlFIGgpcXfqdauhL3mYGLf-mvLBirbD_tbnDo,7875
211
213
  pdd/server/token_counter.py,sha256=cpNX84Ne2hFAqQImvft5mi_6RkBbj7zyqjb4seB0tPk,5628
212
214
  pdd/server/routes/__init__.py,sha256=fotK-A6Vk4h5PAKg_QPdi33Jo39KxizNG9MrgErJNz0,754
213
215
  pdd/server/routes/architecture.py,sha256=XvgUugOgjJ5C6p8ab_Q1oNhMGyE7rXwTRMDhAsJGJgU,14928
@@ -215,13 +217,13 @@ pdd/server/routes/auth.py,sha256=Yp6Tb2_S2WtVZpzbMb_LnL-T2_CMhZR3AHxGzlal_8c,118
215
217
  pdd/server/routes/commands.py,sha256=PEQtPoAF74ByYNmPwujyXjhJN8b5YEjnvb2XYqZDYqM,31608
216
218
  pdd/server/routes/config.py,sha256=7-gPMIpqKs22ogcoj3RtOfCUfaWXxEw1hZX_e3Dlh9k,1043
217
219
  pdd/server/routes/files.py,sha256=qqtoy7Zcy3ixZM9y5T1N6R9i7wxxz-YAzLzwVOyKlCI,21214
218
- pdd/server/routes/prompts.py,sha256=b7UWfnkPtUsfqgVrEDYSdgzpg11sg1PKBgs3R4WH_b8,56371
220
+ pdd/server/routes/prompts.py,sha256=3GpJIBjfWcCFSu_MpUQqYYYDnYjhNKbBgQKdcvhUJRo,57743
219
221
  pdd/server/routes/websocket.py,sha256=lh-65f9ZRLS-QQS-ZTIMi_s72mK_9Ntu6vTfix2hA5o,16185
220
222
  pdd/templates/architecture/architecture_json.prompt,sha256=femVCFSpf51Qj1TsLD-rwF6CcoUz5Iclaxo9p-CpUSI,10912
221
223
  pdd/templates/generic/generate_prompt.prompt,sha256=0qLK-L4kHmd3TKTQT0o9NOwc8DbdFpijTO9dJqPfwOU,10708
222
- pdd_cli-0.0.118.dist-info/licenses/LICENSE,sha256=kvTJnnxPVTYlGKSY4ZN1kzdmJ0lxRdNWxgupaB27zsU,1066
223
- pdd_cli-0.0.118.dist-info/METADATA,sha256=40zA3KbompUkEcvTwwqJzYZDii1vzkWY2otkih2fNUY,13051
224
- pdd_cli-0.0.118.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
225
- pdd_cli-0.0.118.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
226
- pdd_cli-0.0.118.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
227
- pdd_cli-0.0.118.dist-info/RECORD,,
224
+ pdd_cli-0.0.121.dist-info/licenses/LICENSE,sha256=kvTJnnxPVTYlGKSY4ZN1kzdmJ0lxRdNWxgupaB27zsU,1066
225
+ pdd_cli-0.0.121.dist-info/METADATA,sha256=n1DCMHQBpJz5_CmrrljkE1u1_V63ZBE1AF22slKfchk,13051
226
+ pdd_cli-0.0.121.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
227
+ pdd_cli-0.0.121.dist-info/entry_points.txt,sha256=Kr8HtNVb8uHZtQJNH4DnF8j7WNgWQbb7_Pw5hECSR-I,36
228
+ pdd_cli-0.0.121.dist-info/top_level.txt,sha256=xjnhIACeMcMeDfVNREgQZl4EbTni2T11QkL5r7E-sbE,4
229
+ pdd_cli-0.0.121.dist-info/RECORD,,