code-puppy 0.0.52__py3-none-any.whl → 0.0.54__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.
@@ -28,6 +28,7 @@ IGNORE_PATTERNS = [
28
28
  "**/*.exe",
29
29
  ]
30
30
 
31
+
31
32
  def should_ignore_path(path: str) -> bool:
32
33
  """Return True if *path* matches any pattern in IGNORE_PATTERNS."""
33
34
  for pattern in IGNORE_PATTERNS:
@@ -35,12 +36,24 @@ def should_ignore_path(path: str) -> bool:
35
36
  return True
36
37
  return False
37
38
 
38
- def list_files(context: RunContext | None, directory: str = ".", recursive: bool = True) -> List[Dict[str, Any]]:
39
+
40
+ def _list_files(
41
+ context: RunContext, directory: str = ".", recursive: bool = True
42
+ ) -> List[Dict[str, Any]]:
39
43
  """Light-weight `list_files` implementation sufficient for unit-tests and agent tooling."""
44
+ console.print(
45
+ f"\n[bold white on blue] LIST FILES [/bold white on blue] \U0001f4c2 [bold cyan]{directory}[/bold cyan]"
46
+ )
47
+ console.print("[dim]" + "-" * 60 + "[/dim]")
40
48
  directory = os.path.abspath(directory)
41
49
  results: List[Dict[str, Any]] = []
42
50
  if not os.path.exists(directory) or not os.path.isdir(directory):
43
- return [{"error": f"Directory '{directory}' does not exist or is not a directory"}]
51
+ console.print(
52
+ f"[bold red]Directory '{directory}' does not exist or is not a directory[/bold red]"
53
+ )
54
+ return [
55
+ {"error": f"Directory '{directory}' does not exist or is not a directory"}
56
+ ]
44
57
  for root, dirs, files in os.walk(directory):
45
58
  rel_root = os.path.relpath(root, directory)
46
59
  if rel_root == ".":
@@ -52,8 +65,13 @@ def list_files(context: RunContext | None, directory: str = ".", recursive: bool
52
65
  break
53
66
  return results
54
67
 
55
- def read_file(context: RunContext | None, file_path: str) -> Dict[str, Any]:
68
+
69
+ def _read_file(context: RunContext, file_path: str) -> Dict[str, Any]:
56
70
  file_path = os.path.abspath(file_path)
71
+ console.print(
72
+ f"\n[bold white on blue] READ FILE [/bold white on blue] \U0001f4c2 [bold cyan]{file_path}[/bold cyan]"
73
+ )
74
+ console.print("[dim]" + "-" * 60 + "[/dim]")
57
75
  if not os.path.exists(file_path):
58
76
  return {"error": f"File '{file_path}' does not exist"}
59
77
  if not os.path.isfile(file_path):
@@ -61,201 +79,109 @@ def read_file(context: RunContext | None, file_path: str) -> Dict[str, Any]:
61
79
  try:
62
80
  with open(file_path, "r", encoding="utf-8") as f:
63
81
  content = f.read()
64
- return {"content": content, "path": file_path, "total_lines": len(content.splitlines())}
82
+ return {
83
+ "content": content,
84
+ "path": file_path,
85
+ "total_lines": len(content.splitlines()),
86
+ }
65
87
  except Exception as exc:
66
88
  return {"error": str(exc)}
67
89
 
68
- def grep(context: RunContext | None, search_string: str, directory: str = ".") -> List[Dict[str, Any]]:
90
+
91
+ def _grep(
92
+ context: RunContext, search_string: str, directory: str = "."
93
+ ) -> List[Dict[str, Any]]:
69
94
  matches: List[Dict[str, Any]] = []
70
95
  directory = os.path.abspath(directory)
71
- for root, dirs, files in os.walk(directory):
72
- for f in files:
73
- file_path = os.path.join(root, f)
96
+ console.print(
97
+ f"\n[bold white on blue] GREP [/bold white on blue] \U0001f4c2 [bold cyan]{directory}[/bold cyan] [dim]for '{search_string}'[/dim]"
98
+ )
99
+ console.print("[dim]" + "-" * 60 + "[/dim]")
100
+
101
+ for root, dirs, files in os.walk(directory, topdown=True):
102
+ # Filter out ignored directories
103
+ dirs[:] = [d for d in dirs if not should_ignore_path(os.path.join(root, d))]
104
+
105
+ for f_name in files:
106
+ file_path = os.path.join(root, f_name)
107
+
108
+ if should_ignore_path(file_path):
109
+ # console.print(f"[dim]Ignoring: {file_path}[/dim]") # Optional: for debugging ignored files
110
+ continue
111
+
74
112
  try:
75
- with open(file_path, "r", encoding="utf-8") as fh:
76
- for ln, line in enumerate(fh, 1):
77
- if search_string in line:
78
- matches.append({"file_path": file_path, "line_number": ln})
113
+ # console.print(f"\U0001f4c2 [bold cyan]Searching: {file_path}[/bold cyan]") # Optional: for verbose searching log
114
+ with open(file_path, "r", encoding="utf-8", errors="ignore") as fh:
115
+ for line_number, line_content in enumerate(fh, 1):
116
+ if search_string in line_content:
117
+ match_info = {
118
+ "file_path": file_path,
119
+ "line_number": line_number,
120
+ "line_content": line_content.strip(),
121
+ }
122
+ matches.append(match_info)
123
+ # console.print(
124
+ # f"[green]Match:[/green] {file_path}:{line_number} - {line_content.strip()}"
125
+ # ) # Optional: for verbose match logging
79
126
  if len(matches) >= 200:
127
+ console.print(
128
+ "[yellow]Limit of 200 matches reached. Stopping search.[/yellow]"
129
+ )
80
130
  return matches
81
- except Exception:
131
+ except FileNotFoundError:
132
+ console.print(
133
+ f"[yellow]File not found (possibly a broken symlink): {file_path}[/yellow]"
134
+ )
135
+ continue
136
+ except UnicodeDecodeError:
137
+ console.print(
138
+ f"[yellow]Cannot decode file (likely binary): {file_path}[/yellow]"
139
+ )
140
+ continue
141
+ except Exception as e:
142
+ console.print(f"[red]Error processing file {file_path}: {e}[/red]")
82
143
  continue
144
+
145
+ if not matches:
146
+ console.print(
147
+ f"[yellow]No matches found for '{search_string}' in {directory}[/yellow]"
148
+ )
149
+ else:
150
+ console.print(
151
+ f"[green]Found {len(matches)} match(es) for '{search_string}' in {directory}[/green]"
152
+ )
153
+
83
154
  return matches
84
155
 
85
- def register_file_operations_tools(agent):
86
- # Constants for file operations
87
- IGNORE_PATTERNS = [
88
- "**/node_modules/**",
89
- "**/.git/**",
90
- "**/__pycache__/**",
91
- "**/.DS_Store",
92
- "**/.env",
93
- "**/.venv/**",
94
- "**/venv/**",
95
- "**/.idea/**",
96
- "**/.vscode/**",
97
- "**/dist/**",
98
- "**/build/**",
99
- "**/*.pyc",
100
- "**/*.pyo",
101
- "**/*.pyd",
102
- "**/*.so",
103
- "**/*.dll",
104
- "**/*.exe",
105
- ]
106
- def should_ignore_path(path: str) -> bool:
107
- for pattern in IGNORE_PATTERNS:
108
- if fnmatch.fnmatch(path, pattern):
109
- return True
110
- return False
111
156
 
157
+ # Exported top-level functions for direct import by tests and other code
158
+
159
+
160
+ def list_files(context, directory=".", recursive=True):
161
+ return _list_files(context, directory, recursive)
162
+
163
+
164
+ def read_file(context, file_path):
165
+ return _read_file(context, file_path)
166
+
167
+
168
+ def grep(context, search_string, directory="."):
169
+ return _grep(context, search_string, directory)
170
+
171
+
172
+ def register_file_operations_tools(agent):
112
173
  @agent.tool
113
- def list_files(context: RunContext, directory: str = ".", recursive: bool = True) -> List[Dict[str, Any]]:
114
- results = []
115
- directory = os.path.abspath(directory)
116
- console.print("\n[bold white on blue] DIRECTORY LISTING [/bold white on blue]")
117
- console.print(f"\U0001F4C2 [bold cyan]{directory}[/bold cyan] [dim](recursive={recursive})[/dim]")
118
- console.print("[dim]" + "-" * 60 + "[/dim]")
119
- if not os.path.exists(directory):
120
- console.print(f"[bold red]Error:[/bold red] Directory '{directory}' does not exist")
121
- console.print("[dim]" + "-" * 60 + "[/dim]\n")
122
- return [{"error": f"Directory '{directory}' does not exist"}]
123
- if not os.path.isdir(directory):
124
- console.print(f"[bold red]Error:[/bold red] '{directory}' is not a directory")
125
- console.print("[dim]" + "-" * 60 + "[/dim]\n")
126
- return [{"error": f"'{directory}' is not a directory"}]
127
- folder_structure = {}
128
- file_list = []
129
- for root, dirs, files in os.walk(directory):
130
- dirs[:] = [d for d in dirs if not should_ignore_path(os.path.join(root, d))]
131
- rel_path = os.path.relpath(root, directory)
132
- depth = 0 if rel_path == "." else rel_path.count(os.sep) + 1
133
- if rel_path == ".":
134
- rel_path = ""
135
- if rel_path:
136
- dir_path = os.path.join(directory, rel_path)
137
- results.append({"path": rel_path, "type": "directory", "size": 0, "full_path": dir_path, "depth": depth})
138
- folder_structure[rel_path] = {"path": rel_path, "depth": depth, "full_path": dir_path}
139
- for file in files:
140
- file_path = os.path.join(root, file)
141
- if should_ignore_path(file_path):
142
- continue
143
- rel_file_path = os.path.join(rel_path, file) if rel_path else file
144
- try:
145
- size = os.path.getsize(file_path)
146
- file_info = {"path": rel_file_path, "type": "file", "size": size, "full_path": file_path, "depth": depth}
147
- results.append(file_info)
148
- file_list.append(file_info)
149
- except (FileNotFoundError, PermissionError):
150
- continue
151
- if not recursive:
152
- break
153
- def format_size(size_bytes):
154
- if size_bytes < 1024:
155
- return f"{size_bytes} B"
156
- elif size_bytes < 1024*1024:
157
- return f"{size_bytes/1024:.1f} KB"
158
- elif size_bytes < 1024*1024*1024:
159
- return f"{size_bytes/(1024*1024):.1f} MB"
160
- else:
161
- return f"{size_bytes/(1024*1024*1024):.1f} GB"
162
- def get_file_icon(file_path):
163
- ext = os.path.splitext(file_path)[1].lower()
164
- if ext in [".py", ".pyw"]:
165
- return "\U0001F40D"
166
- elif ext in [".js", ".jsx", ".ts", ".tsx"]:
167
- return "\U0001F4DC"
168
- elif ext in [".html", ".htm", ".xml"]:
169
- return "\U0001F310"
170
- elif ext in [".css", ".scss", ".sass"]:
171
- return "\U0001F3A8"
172
- elif ext in [".md", ".markdown", ".rst"]:
173
- return "\U0001F4DD"
174
- elif ext in [".json", ".yaml", ".yml", ".toml"]:
175
- return "\u2699\ufe0f"
176
- elif ext in [".jpg", ".jpeg", ".png", ".gif", ".svg", ".webp"]:
177
- return "\U0001F5BC\ufe0f"
178
- elif ext in [".mp3", ".wav", ".ogg", ".flac"]:
179
- return "\U0001F3B5"
180
- elif ext in [".mp4", ".avi", ".mov", ".webm"]:
181
- return "\U0001F3AC"
182
- elif ext in [".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx"]:
183
- return "\U0001F4C4"
184
- elif ext in [".zip", ".tar", ".gz", ".rar", ".7z"]:
185
- return "\U0001F4E6"
186
- elif ext in [".exe", ".dll", ".so", ".dylib"]:
187
- return "\u26A1"
188
- else:
189
- return "\U0001F4C4"
190
- if results:
191
- files = sorted([f for f in results if f["type"] == "file"], key=lambda x: x["path"])
192
- console.print(f"\U0001F4C1 [bold blue]{os.path.basename(directory) or directory}[/bold blue]")
193
- all_items = sorted(results, key=lambda x: x["path"])
194
- parent_dirs_with_content = set()
195
- for i, item in enumerate(all_items):
196
- if item["type"] == "directory" and not item["path"]:
197
- continue
198
- if os.sep in item["path"]:
199
- parent_path = os.path.dirname(item["path"])
200
- parent_dirs_with_content.add(parent_path)
201
- depth = item["path"].count(os.sep) + 1 if item["path"] else 0
202
- prefix = ""
203
- for d in range(depth):
204
- if d == depth - 1:
205
- prefix += "\u2514\u2500\u2500 "
206
- else:
207
- prefix += " "
208
- name = os.path.basename(item["path"]) or item["path"]
209
- if item["type"] == "directory":
210
- console.print(f"{prefix}\U0001F4C1 [bold blue]{name}/[/bold blue]")
211
- else:
212
- icon = get_file_icon(item["path"])
213
- size_str = format_size(item["size"])
214
- console.print(f"{prefix}{icon} [green]{name}[/green] [dim]({size_str})[/dim]")
215
- else:
216
- console.print("[yellow]Directory is empty[/yellow]")
217
- dir_count = sum(1 for item in results if item["type"] == "directory")
218
- file_count = sum(1 for item in results if item["type"] == "file")
219
- total_size = sum(item["size"] for item in results if item["type"] == "file")
220
- console.print("\n[bold cyan]Summary:[/bold cyan]")
221
- console.print(f"\U0001F4C1 [blue]{dir_count} directories[/blue], \U0001F4C4 [green]{file_count} files[/green] [dim]({format_size(total_size)} total)[/dim]")
222
- console.print("[dim]" + "-" * 60 + "[/dim]\n")
223
- return results
174
+ def list_files(
175
+ context: RunContext, directory: str = ".", recursive: bool = True
176
+ ) -> List[Dict[str, Any]]:
177
+ return _list_files(context, directory, recursive)
224
178
 
225
179
  @agent.tool
226
180
  def read_file(context: RunContext, file_path: str) -> Dict[str, Any]:
227
- file_path = os.path.abspath(file_path)
228
- if not os.path.exists(file_path):
229
- return {"error": f"File '{file_path}' does not exist"}
230
- if not os.path.isfile(file_path):
231
- return {"error": f"'{file_path}' is not a file"}
232
- try:
233
- with open(file_path, "r", encoding="utf-8") as f:
234
- content = f.read()
235
- _, ext = os.path.splitext(file_path)
236
- return {"content": content, "path": file_path, "extension": ext.lstrip("."), "total_lines": len(content.splitlines())}
237
- except UnicodeDecodeError:
238
- return {"error": f"Cannot read '{file_path}' as text - it may be a binary file"}
239
- except Exception as e:
240
- return {"error": f"Error reading file '{file_path}': {str(e)}"}
181
+ return _read_file(context, file_path)
241
182
 
242
183
  @agent.tool
243
- def grep(context: RunContext, search_string: str, directory: str = ".") -> List[Dict[str, Any]]:
244
- matches = []
245
- max_matches = 200
246
- directory = os.path.abspath(directory)
247
- for root, dirs, files in os.walk(directory):
248
- for file in files:
249
- file_path = os.path.join(root, file)
250
- if should_ignore_path(file_path):
251
- continue
252
- try:
253
- with open(file_path, "r", encoding="utf-8") as f:
254
- for line_number, line in enumerate(f, start=1):
255
- if search_string in line:
256
- matches.append({"file_path": file_path, "line_number": line_number})
257
- if len(matches) >= max_matches:
258
- return matches
259
- except (FileNotFoundError, PermissionError, UnicodeDecodeError):
260
- continue
261
- return matches
184
+ def grep(
185
+ context: RunContext, search_string: str, directory: str = "."
186
+ ) -> List[Dict[str, Any]]:
187
+ return _grep(context, search_string, directory)
@@ -2,14 +2,30 @@ from typing import Dict
2
2
  import requests
3
3
  from pydantic_ai import RunContext
4
4
 
5
+
5
6
  def register_web_search_tools(agent):
6
7
  @agent.tool
7
8
  def grab_json_from_url(context: RunContext, url: str) -> Dict:
8
- response = requests.get(url)
9
- response.raise_for_status()
10
- if response.headers.get('Content-Type') != 'application/json':
11
- raise ValueError(f"Response from {url} is not of type application/json")
12
- json_data = response.json()
13
- if isinstance(json_data, list) and len(json_data) > 1000:
14
- return json_data[:1000]
15
- return json_data
9
+ from code_puppy.tools.common import console
10
+
11
+ try:
12
+ response = requests.get(url)
13
+ response.raise_for_status()
14
+ ct = response.headers.get("Content-Type")
15
+ if "json" not in str(ct):
16
+ console.print(
17
+ f"[bold red]Error:[/bold red] Response from {url} is not JSON (got {ct})"
18
+ )
19
+ return {"error": f"Response from {url} is not of type application/json"}
20
+ json_data = response.json()
21
+ if isinstance(json_data, list) and len(json_data) > 1000:
22
+ console.print("[yellow]Result list truncated to 1000 items[/yellow]")
23
+ return json_data[:1000]
24
+ if not json_data:
25
+ console.print("[yellow]No data found for URL:[/yellow]", url)
26
+ else:
27
+ console.print(f"[green]Successfully fetched JSON from:[/green] {url}")
28
+ return json_data
29
+ except Exception as exc:
30
+ console.print(f"[bold red]Error:[/bold red] {exc}")
31
+ return {"error": str(exc)}
@@ -3,10 +3,10 @@ import requests
3
3
 
4
4
  def fetch_latest_version(package_name):
5
5
  try:
6
- response = requests.get(f'https://pypi.org/pypi/{package_name}/json')
6
+ response = requests.get(f"https://pypi.org/pypi/{package_name}/json")
7
7
  response.raise_for_status() # Raise an error for bad responses
8
8
  data = response.json()
9
- return data['info']['version']
9
+ return data["info"]["version"]
10
10
  except requests.RequestException as e:
11
- print(f'Error fetching version: {e}')
12
- return None
11
+ print(f"Error fetching version: {e}")
12
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-puppy
3
- Version: 0.0.52
3
+ Version: 0.0.54
4
4
  Summary: Code generation agent
5
5
  Author: Michael Pfaffenberger
6
6
  License: MIT
@@ -0,0 +1,28 @@
1
+ code_puppy/__init__.py,sha256=-ANvE6Xe5NlWDIRCIfL1x-rgtCZ6zM2Ye9NphFoULSY,82
2
+ code_puppy/agent.py,sha256=yA2247YbmBdff37joH8lRDKFk-iYreCugjY4qrdmsgA,3238
3
+ code_puppy/agent_prompts.py,sha256=mUt9a430x0aYbnCw4L6t-Wst1_0FcqKYka_RHtnRog0,6774
4
+ code_puppy/config.py,sha256=Mn9VWj8Ux-qnl636BH0jE1tuM-HQ6bYmRaozMg-vbg8,3941
5
+ code_puppy/main.py,sha256=mLnECoA5b20Jb_9PUIznsMKOmChIjvX0lEpT69Dx7y4,10370
6
+ code_puppy/model_factory.py,sha256=AtCBAWEK6OmPHL79HG3J-MxvlMbXJ9s4SBNblcZKemM,11645
7
+ code_puppy/models.json,sha256=7H-y97YK9BXhag5wJU19rtg24JtZWYx60RsBLBW3WiI,2162
8
+ code_puppy/session_memory.py,sha256=CODAMmSsrxh8N9x_dXLryOSW3GnBXJ70auJnHm4m5Z8,2735
9
+ code_puppy/version_checker.py,sha256=aRGulzuY4C4CdFvU1rITduyL-1xTFsn4GiD1uSfOl_Y,396
10
+ code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
11
+ code_puppy/command_line/file_path_completion.py,sha256=WSGpUO5PwpqxxJAhdjzUEWjJCxGWPUl5GU95KTg_Y40,2930
12
+ code_puppy/command_line/meta_command_handler.py,sha256=XqidNJYaoYMaHcFI85RwwKYElEhPXgedkXwauw_4C60,5569
13
+ code_puppy/command_line/model_picker_completion.py,sha256=QHxzhgTvbGFw0EYFJAukcWB3JTuK4Z1ZWaYvygMqfgM,3731
14
+ code_puppy/command_line/prompt_toolkit_completion.py,sha256=PyPo3H4CInBCbtddI91Owgwi1tKzWu9ryADOWWWMfHI,7942
15
+ code_puppy/command_line/utils.py,sha256=_3wEvtJbey4E4qdg4pFX29sDPucRKGTyuodKI__NVrQ,1250
16
+ code_puppy/tools/__init__.py,sha256=B1sHgH9mONPmWiGb6vucCIKzoRBlhM7UBxtfSRU1AEY,558
17
+ code_puppy/tools/code_map.py,sha256=eAIT6IKEpq4OE6gE64HOjGMgEcPeJVEGb1eBHmFwaxY,3200
18
+ code_puppy/tools/command_runner.py,sha256=m-0emolt81BvKuiEUBW8VPzrA1wgA_sXRJFmySPtxqA,6514
19
+ code_puppy/tools/common.py,sha256=qX6wWsZPU9mwHX0AS2RIGIEQtQJ_AeWZ799LUvOCbfs,146
20
+ code_puppy/tools/file_modifications.py,sha256=onhmNwlMlOD0BrnMH_1QGiwZQu0qAAiiN2dHRilzBHA,16124
21
+ code_puppy/tools/file_operations.py,sha256=yEHeVS9S3S_iGpeqF3n9448oFSknaD2DbjIDY_URF54,6755
22
+ code_puppy/tools/web_search.py,sha256=GvUJJUDQ_5VHkd_YJkRUWJdqr0Y-XSZIyzmUHHiVcus,1283
23
+ code_puppy-0.0.54.data/data/code_puppy/models.json,sha256=7H-y97YK9BXhag5wJU19rtg24JtZWYx60RsBLBW3WiI,2162
24
+ code_puppy-0.0.54.dist-info/METADATA,sha256=6Y47f2cg5QxI3a7hs6WWbf51UQf3fEKLdXL0f7l9fkM,4716
25
+ code_puppy-0.0.54.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
+ code_puppy-0.0.54.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
27
+ code_puppy-0.0.54.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
28
+ code_puppy-0.0.54.dist-info/RECORD,,
@@ -1,28 +0,0 @@
1
- code_puppy/__init__.py,sha256=orgffM-uGp8g1XCqXGKWaFB4tCCz8TVgsLMPKCOGNx0,81
2
- code_puppy/agent.py,sha256=avoOEorAYUyQYnYVVCezLz1QKDm0Qgx3i_C-BqgDiQQ,3198
3
- code_puppy/agent_prompts.py,sha256=A6ADydqbHozIAtwOy_UY-fYZ2XDE9_5oV3oxOMtVCFA,6782
4
- code_puppy/config.py,sha256=jsPnwDjz_H69Oww5JyEg3eud3rYMKp3ah2WrnablRak,3894
5
- code_puppy/main.py,sha256=_xm5qCLnG2al4yVtoq9dGkOu0CBsLlHLZEoDiPAmVAI,10220
6
- code_puppy/model_factory.py,sha256=vDlEoEKkOoikExCqi5oxb_PuTF8STUMABXAbPHV_p34,11639
7
- code_puppy/models.json,sha256=7H-y97YK9BXhag5wJU19rtg24JtZWYx60RsBLBW3WiI,2162
8
- code_puppy/session_memory.py,sha256=vuLSw1Pfa-MXD4lD8hj2qt65OR_aL2WdoMuF6Jwnc1k,2597
9
- code_puppy/version_checker.py,sha256=cK-eU7Y_yYjn7feIONqzzZUdiedozL0iiKXlGKjfq68,395
10
- code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
11
- code_puppy/command_line/file_path_completion.py,sha256=HAlOu9XVYgJ7FbjdrhKBL0rFmCVFxSGGewdcfKTUsPw,2865
12
- code_puppy/command_line/meta_command_handler.py,sha256=YKXthyXl-4J0MixdTtzABK_E8ReDEBGi3ftGICglwUA,5407
13
- code_puppy/command_line/model_picker_completion.py,sha256=5VEa6OE9shsF0EafJXzBLpFXhFIkqevJi9RRD-eUvZA,3718
14
- code_puppy/command_line/prompt_toolkit_completion.py,sha256=R-ykRmhVTieE4zIQnn7H1GDKk32yvalot0rZpFizLAQ,7358
15
- code_puppy/command_line/utils.py,sha256=L1PnV9tNupEW1zeziyb5aGAq8DYP8sMiuQbFYLO5Nus,1236
16
- code_puppy/tools/__init__.py,sha256=48BVpMt0HAMtz8G_z9SQhX6LnRqR83_AVfMQMf7bY0g,557
17
- code_puppy/tools/code_map.py,sha256=BghDHaebhGDfDGvA34gwO_5r92Py4O0Q3J4RV-WtnWs,3155
18
- code_puppy/tools/command_runner.py,sha256=eg7pOIMkuHtNYVqVE1pPsNYSR2D6XXnkwFaBKd-Ejc8,4773
19
- code_puppy/tools/common.py,sha256=dbmyZTrTBQh_0WWpaYN6jEync62W2mMrzNS8UFK0co4,146
20
- code_puppy/tools/file_modifications.py,sha256=nT87uAoY14RTAapnFCgkLTmW9g9P9bymxts2MpSpoo0,19297
21
- code_puppy/tools/file_operations.py,sha256=LJU_1b3WCXTAHa2B5VAbckrn1VVWb-HhcI3TF3BxYWs,11625
22
- code_puppy/tools/web_search.py,sha256=HhcwX0MMvMDPFO8gr8gzgesD5wPXOypjkxyLZeNwL5g,589
23
- code_puppy-0.0.52.data/data/code_puppy/models.json,sha256=7H-y97YK9BXhag5wJU19rtg24JtZWYx60RsBLBW3WiI,2162
24
- code_puppy-0.0.52.dist-info/METADATA,sha256=06k73QklKcPlf-plfu2-wmaMzosKy7qrqaFSamlYkXo,4716
25
- code_puppy-0.0.52.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
26
- code_puppy-0.0.52.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
27
- code_puppy-0.0.52.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
28
- code_puppy-0.0.52.dist-info/RECORD,,