code-puppy 0.0.336__py3-none-any.whl → 0.0.341__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.
- code_puppy/agents/base_agent.py +79 -31
- code_puppy/claude_cache_client.py +208 -2
- code_puppy/cli_runner.py +49 -32
- code_puppy/command_line/autosave_menu.py +18 -24
- code_puppy/command_line/clipboard.py +527 -0
- code_puppy/command_line/core_commands.py +34 -0
- code_puppy/command_line/prompt_toolkit_completion.py +118 -0
- code_puppy/http_utils.py +93 -130
- code_puppy/mcp_/managed_server.py +7 -11
- code_puppy/messaging/messages.py +3 -0
- code_puppy/messaging/rich_renderer.py +13 -3
- code_puppy/model_factory.py +16 -0
- code_puppy/models.json +2 -2
- code_puppy/plugins/antigravity_oauth/antigravity_model.py +17 -2
- code_puppy/plugins/claude_code_oauth/utils.py +126 -7
- code_puppy/terminal_utils.py +128 -1
- code_puppy/tools/command_runner.py +1 -0
- code_puppy/tools/common.py +3 -9
- {code_puppy-0.0.336.data → code_puppy-0.0.341.data}/data/code_puppy/models.json +2 -2
- {code_puppy-0.0.336.dist-info → code_puppy-0.0.341.dist-info}/METADATA +19 -71
- {code_puppy-0.0.336.dist-info → code_puppy-0.0.341.dist-info}/RECORD +25 -24
- {code_puppy-0.0.336.data → code_puppy-0.0.341.data}/data/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.336.dist-info → code_puppy-0.0.341.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.336.dist-info → code_puppy-0.0.341.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.336.dist-info → code_puppy-0.0.341.dist-info}/licenses/LICENSE +0 -0
|
@@ -21,6 +21,8 @@ from .config import (
|
|
|
21
21
|
get_token_storage_path,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
+
TOKEN_REFRESH_BUFFER_SECONDS = 60
|
|
25
|
+
|
|
24
26
|
logger = logging.getLogger(__name__)
|
|
25
27
|
|
|
26
28
|
|
|
@@ -132,6 +134,124 @@ def load_stored_tokens() -> Optional[Dict[str, Any]]:
|
|
|
132
134
|
return None
|
|
133
135
|
|
|
134
136
|
|
|
137
|
+
def _calculate_expires_at(expires_in: Optional[float]) -> Optional[float]:
|
|
138
|
+
if expires_in is None:
|
|
139
|
+
return None
|
|
140
|
+
try:
|
|
141
|
+
return time.time() + float(expires_in)
|
|
142
|
+
except (TypeError, ValueError):
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def is_token_expired(tokens: Dict[str, Any]) -> bool:
|
|
147
|
+
expires_at = tokens.get("expires_at")
|
|
148
|
+
if expires_at is None:
|
|
149
|
+
return False
|
|
150
|
+
try:
|
|
151
|
+
expires_at_value = float(expires_at)
|
|
152
|
+
except (TypeError, ValueError):
|
|
153
|
+
return False
|
|
154
|
+
return time.time() >= expires_at_value - TOKEN_REFRESH_BUFFER_SECONDS
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def update_claude_code_model_tokens(access_token: str) -> bool:
|
|
158
|
+
try:
|
|
159
|
+
claude_models = load_claude_models()
|
|
160
|
+
if not claude_models:
|
|
161
|
+
return False
|
|
162
|
+
|
|
163
|
+
updated = False
|
|
164
|
+
for config in claude_models.values():
|
|
165
|
+
if config.get("oauth_source") != "claude-code-plugin":
|
|
166
|
+
continue
|
|
167
|
+
custom_endpoint = config.get("custom_endpoint")
|
|
168
|
+
if not isinstance(custom_endpoint, dict):
|
|
169
|
+
continue
|
|
170
|
+
custom_endpoint["api_key"] = access_token
|
|
171
|
+
updated = True
|
|
172
|
+
|
|
173
|
+
if updated:
|
|
174
|
+
return save_claude_models(claude_models)
|
|
175
|
+
except Exception as exc: # pragma: no cover - defensive logging
|
|
176
|
+
logger.error("Failed to update Claude model tokens: %s", exc)
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def refresh_access_token(force: bool = False) -> Optional[str]:
|
|
181
|
+
tokens = load_stored_tokens()
|
|
182
|
+
if not tokens:
|
|
183
|
+
return None
|
|
184
|
+
|
|
185
|
+
if not force and not is_token_expired(tokens):
|
|
186
|
+
return tokens.get("access_token")
|
|
187
|
+
|
|
188
|
+
refresh_token = tokens.get("refresh_token")
|
|
189
|
+
if not refresh_token:
|
|
190
|
+
logger.debug("No refresh_token available")
|
|
191
|
+
return None
|
|
192
|
+
|
|
193
|
+
payload = {
|
|
194
|
+
"grant_type": "refresh_token",
|
|
195
|
+
"client_id": CLAUDE_CODE_OAUTH_CONFIG["client_id"],
|
|
196
|
+
"refresh_token": refresh_token,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
headers = {
|
|
200
|
+
"Content-Type": "application/json",
|
|
201
|
+
"Accept": "application/json",
|
|
202
|
+
"anthropic-beta": "oauth-2025-04-20",
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
response = requests.post(
|
|
207
|
+
CLAUDE_CODE_OAUTH_CONFIG["token_url"],
|
|
208
|
+
json=payload,
|
|
209
|
+
headers=headers,
|
|
210
|
+
timeout=30,
|
|
211
|
+
)
|
|
212
|
+
if response.status_code == 200:
|
|
213
|
+
new_tokens = response.json()
|
|
214
|
+
tokens["access_token"] = new_tokens.get("access_token")
|
|
215
|
+
tokens["refresh_token"] = new_tokens.get("refresh_token", refresh_token)
|
|
216
|
+
if "expires_in" in new_tokens:
|
|
217
|
+
tokens["expires_in"] = new_tokens["expires_in"]
|
|
218
|
+
tokens["expires_at"] = _calculate_expires_at(
|
|
219
|
+
new_tokens.get("expires_in")
|
|
220
|
+
)
|
|
221
|
+
if save_tokens(tokens):
|
|
222
|
+
update_claude_code_model_tokens(tokens["access_token"])
|
|
223
|
+
return tokens["access_token"]
|
|
224
|
+
else:
|
|
225
|
+
logger.error(
|
|
226
|
+
"Token refresh failed: %s - %s", response.status_code, response.text
|
|
227
|
+
)
|
|
228
|
+
except Exception as exc: # pragma: no cover - defensive logging
|
|
229
|
+
logger.error("Token refresh error: %s", exc)
|
|
230
|
+
return None
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def get_valid_access_token() -> Optional[str]:
|
|
234
|
+
tokens = load_stored_tokens()
|
|
235
|
+
if not tokens:
|
|
236
|
+
logger.debug("No stored Claude Code OAuth tokens found")
|
|
237
|
+
return None
|
|
238
|
+
|
|
239
|
+
access_token = tokens.get("access_token")
|
|
240
|
+
if not access_token:
|
|
241
|
+
logger.debug("No access_token in stored tokens")
|
|
242
|
+
return None
|
|
243
|
+
|
|
244
|
+
if is_token_expired(tokens):
|
|
245
|
+
logger.info("Claude Code OAuth token expired, attempting refresh")
|
|
246
|
+
refreshed = refresh_access_token()
|
|
247
|
+
if refreshed:
|
|
248
|
+
return refreshed
|
|
249
|
+
logger.warning("Claude Code token refresh failed")
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
return access_token
|
|
253
|
+
|
|
254
|
+
|
|
135
255
|
def save_tokens(tokens: Dict[str, Any]) -> bool:
|
|
136
256
|
try:
|
|
137
257
|
token_path = get_token_storage_path()
|
|
@@ -243,7 +363,11 @@ def exchange_code_for_tokens(
|
|
|
243
363
|
logger.info("Token exchange response: %s", response.status_code)
|
|
244
364
|
logger.debug("Response body: %s", response.text)
|
|
245
365
|
if response.status_code == 200:
|
|
246
|
-
|
|
366
|
+
token_data = response.json()
|
|
367
|
+
token_data["expires_at"] = _calculate_expires_at(
|
|
368
|
+
token_data.get("expires_in")
|
|
369
|
+
)
|
|
370
|
+
return token_data
|
|
247
371
|
logger.error(
|
|
248
372
|
"Token exchange failed: %s - %s",
|
|
249
373
|
response.status_code,
|
|
@@ -341,12 +465,7 @@ def add_models_to_extra_config(models: List[str]) -> bool:
|
|
|
341
465
|
# Start fresh - overwrite the file on every auth instead of loading existing
|
|
342
466
|
claude_models = {}
|
|
343
467
|
added = 0
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
# Handle case where tokens are None or empty
|
|
347
|
-
access_token = ""
|
|
348
|
-
if tokens and "access_token" in tokens:
|
|
349
|
-
access_token = tokens["access_token"]
|
|
468
|
+
access_token = get_valid_access_token() or ""
|
|
350
469
|
|
|
351
470
|
for model_name in filtered_models:
|
|
352
471
|
prefixed = f"{CLAUDE_CODE_OAUTH_CONFIG['prefix']}{model_name}"
|
code_puppy/terminal_utils.py
CHANGED
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
Handles Windows console mode resets and Unix terminal sanity restoration.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
import os
|
|
6
7
|
import platform
|
|
7
8
|
import subprocess
|
|
8
9
|
import sys
|
|
9
|
-
from typing import Callable, Optional
|
|
10
|
+
from typing import TYPE_CHECKING, Callable, Optional
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from rich.console import Console
|
|
10
14
|
|
|
11
15
|
# Store the original console ctrl handler so we can restore it if needed
|
|
12
16
|
_original_ctrl_handler: Optional[Callable] = None
|
|
@@ -289,3 +293,126 @@ def ensure_ctrl_c_disabled() -> bool:
|
|
|
289
293
|
|
|
290
294
|
except Exception:
|
|
291
295
|
return False
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def detect_truecolor_support() -> bool:
|
|
299
|
+
"""Detect if the terminal supports truecolor (24-bit color).
|
|
300
|
+
|
|
301
|
+
Checks multiple indicators:
|
|
302
|
+
1. COLORTERM environment variable (most reliable)
|
|
303
|
+
2. TERM environment variable patterns
|
|
304
|
+
3. Rich's Console color_system detection as fallback
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
True if truecolor is supported, False otherwise.
|
|
308
|
+
"""
|
|
309
|
+
# Check COLORTERM - this is the most reliable indicator
|
|
310
|
+
colorterm = os.environ.get("COLORTERM", "").lower()
|
|
311
|
+
if colorterm in ("truecolor", "24bit"):
|
|
312
|
+
return True
|
|
313
|
+
|
|
314
|
+
# Check TERM for known truecolor-capable terminals
|
|
315
|
+
term = os.environ.get("TERM", "").lower()
|
|
316
|
+
truecolor_terms = (
|
|
317
|
+
"xterm-direct",
|
|
318
|
+
"xterm-truecolor",
|
|
319
|
+
"iterm2",
|
|
320
|
+
"vte-256color", # Many modern terminals set this
|
|
321
|
+
)
|
|
322
|
+
if any(t in term for t in truecolor_terms):
|
|
323
|
+
return True
|
|
324
|
+
|
|
325
|
+
# Some terminals like iTerm2, Kitty, Alacritty set specific env vars
|
|
326
|
+
if os.environ.get("ITERM_SESSION_ID"):
|
|
327
|
+
return True
|
|
328
|
+
if os.environ.get("KITTY_WINDOW_ID"):
|
|
329
|
+
return True
|
|
330
|
+
if os.environ.get("ALACRITTY_SOCKET"):
|
|
331
|
+
return True
|
|
332
|
+
if os.environ.get("WT_SESSION"): # Windows Terminal
|
|
333
|
+
return True
|
|
334
|
+
|
|
335
|
+
# Use Rich's detection as a fallback
|
|
336
|
+
try:
|
|
337
|
+
from rich.console import Console
|
|
338
|
+
|
|
339
|
+
console = Console(force_terminal=True)
|
|
340
|
+
color_system = console.color_system
|
|
341
|
+
return color_system == "truecolor"
|
|
342
|
+
except Exception:
|
|
343
|
+
pass
|
|
344
|
+
|
|
345
|
+
return False
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def print_truecolor_warning(console: Optional["Console"] = None) -> None:
|
|
349
|
+
"""Print a big fat red warning if truecolor is not supported.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
console: Optional Rich Console instance. If None, creates a new one.
|
|
353
|
+
"""
|
|
354
|
+
if detect_truecolor_support():
|
|
355
|
+
return # All good, no warning needed
|
|
356
|
+
|
|
357
|
+
if console is None:
|
|
358
|
+
try:
|
|
359
|
+
from rich.console import Console
|
|
360
|
+
|
|
361
|
+
console = Console()
|
|
362
|
+
except ImportError:
|
|
363
|
+
# Rich not available, fall back to plain print
|
|
364
|
+
print("\n" + "=" * 70)
|
|
365
|
+
print("⚠️ WARNING: TERMINAL DOES NOT SUPPORT TRUECOLOR (24-BIT COLOR)")
|
|
366
|
+
print("=" * 70)
|
|
367
|
+
print("Code Puppy looks best with truecolor support.")
|
|
368
|
+
print("Consider using a modern terminal like:")
|
|
369
|
+
print(" • iTerm2 (macOS)")
|
|
370
|
+
print(" • Windows Terminal (Windows)")
|
|
371
|
+
print(" • Kitty, Alacritty, or any modern terminal emulator")
|
|
372
|
+
print("")
|
|
373
|
+
print("You can also try setting: export COLORTERM=truecolor")
|
|
374
|
+
print("")
|
|
375
|
+
print("Note: The built-in macOS Terminal.app does not support truecolor")
|
|
376
|
+
print("(Sequoia and earlier). You'll need a different terminal app.")
|
|
377
|
+
print("=" * 70 + "\n")
|
|
378
|
+
return
|
|
379
|
+
|
|
380
|
+
# Get detected color system for diagnostic info
|
|
381
|
+
color_system = console.color_system or "unknown"
|
|
382
|
+
|
|
383
|
+
# Build the warning box
|
|
384
|
+
warning_lines = [
|
|
385
|
+
"",
|
|
386
|
+
"[bold bright_red on red]" + "━" * 72 + "[/]",
|
|
387
|
+
"[bold bright_red on red]┃[/][bold bright_white on red]"
|
|
388
|
+
+ " " * 70
|
|
389
|
+
+ "[/][bold bright_red on red]┃[/]",
|
|
390
|
+
"[bold bright_red on red]┃[/][bold bright_white on red] ⚠️ WARNING: TERMINAL DOES NOT SUPPORT TRUECOLOR (24-BIT COLOR) ⚠️ [/][bold bright_red on red]┃[/]",
|
|
391
|
+
"[bold bright_red on red]┃[/][bold bright_white on red]"
|
|
392
|
+
+ " " * 70
|
|
393
|
+
+ "[/][bold bright_red on red]┃[/]",
|
|
394
|
+
"[bold bright_red on red]" + "━" * 72 + "[/]",
|
|
395
|
+
"",
|
|
396
|
+
f"[yellow]Detected color system:[/] [bold]{color_system}[/]",
|
|
397
|
+
"",
|
|
398
|
+
"[bold white]Code Puppy uses rich colors and will look degraded without truecolor.[/]",
|
|
399
|
+
"",
|
|
400
|
+
"[cyan]Consider using a modern terminal emulator:[/]",
|
|
401
|
+
" [green]•[/] [bold]iTerm2[/] (macOS) - https://iterm2.com",
|
|
402
|
+
" [green]•[/] [bold]Windows Terminal[/] (Windows) - Built into Windows 11",
|
|
403
|
+
" [green]•[/] [bold]Kitty[/] - https://sw.kovidgoyal.net/kitty",
|
|
404
|
+
" [green]•[/] [bold]Alacritty[/] - https://alacritty.org",
|
|
405
|
+
" [green]•[/] [bold]Warp[/] (macOS) - https://warp.dev",
|
|
406
|
+
"",
|
|
407
|
+
"[cyan]Or try setting the COLORTERM environment variable:[/]",
|
|
408
|
+
" [dim]export COLORTERM=truecolor[/]",
|
|
409
|
+
"",
|
|
410
|
+
"[dim italic]Note: The built-in macOS Terminal.app does not support truecolor (Sequoia and earlier).[/]",
|
|
411
|
+
"[dim italic]Setting COLORTERM=truecolor won't help - you'll need a different terminal app.[/]",
|
|
412
|
+
"",
|
|
413
|
+
"[bold bright_red]" + "─" * 72 + "[/]",
|
|
414
|
+
"",
|
|
415
|
+
]
|
|
416
|
+
|
|
417
|
+
for line in warning_lines:
|
|
418
|
+
console.print(line)
|
code_puppy/tools/common.py
CHANGED
|
@@ -727,15 +727,9 @@ def _format_diff_with_syntax_highlighting(
|
|
|
727
727
|
result.append("\n")
|
|
728
728
|
continue
|
|
729
729
|
|
|
730
|
-
#
|
|
731
|
-
if line.startswith("---"):
|
|
732
|
-
|
|
733
|
-
elif line.startswith("+++"):
|
|
734
|
-
result.append(line, style="yellow")
|
|
735
|
-
elif line.startswith("@@"):
|
|
736
|
-
result.append(line, style="cyan")
|
|
737
|
-
elif line.startswith(("diff ", "index ")):
|
|
738
|
-
result.append(line, style="dim")
|
|
730
|
+
# Skip diff headers - they're redundant noise since we show the filename in the banner
|
|
731
|
+
if line.startswith(("---", "+++", "@@", "diff ", "index ")):
|
|
732
|
+
continue
|
|
739
733
|
else:
|
|
740
734
|
# Determine line type and extract code content
|
|
741
735
|
if line.startswith("-"):
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
"supported_settings": ["reasoning_effort", "verbosity"],
|
|
56
56
|
"supports_xhigh_reasoning": true
|
|
57
57
|
},
|
|
58
|
-
"Cerebras-GLM-4.
|
|
58
|
+
"Cerebras-GLM-4.7": {
|
|
59
59
|
"type": "cerebras",
|
|
60
|
-
"name": "zai-glm-4.
|
|
60
|
+
"name": "zai-glm-4.7",
|
|
61
61
|
"custom_endpoint": {
|
|
62
62
|
"url": "https://api.cerebras.ai/v1",
|
|
63
63
|
"api_key": "$CEREBRAS_API_KEY"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.341
|
|
4
4
|
Summary: Code generation agent
|
|
5
5
|
Project-URL: repository, https://github.com/mpfaffenberger/code_puppy
|
|
6
6
|
Project-URL: HomePage, https://github.com/mpfaffenberger/code_puppy
|
|
@@ -22,6 +22,7 @@ Requires-Dist: httpx[http2]>=0.24.1
|
|
|
22
22
|
Requires-Dist: json-repair>=0.46.2
|
|
23
23
|
Requires-Dist: logfire>=0.7.1
|
|
24
24
|
Requires-Dist: openai>=1.99.1
|
|
25
|
+
Requires-Dist: pillow>=10.0.0
|
|
25
26
|
Requires-Dist: playwright>=1.40.0
|
|
26
27
|
Requires-Dist: prompt-toolkit>=3.0.52
|
|
27
28
|
Requires-Dist: pydantic-ai==1.25.0
|
|
@@ -34,6 +35,7 @@ Requires-Dist: rich>=13.4.2
|
|
|
34
35
|
Requires-Dist: ripgrep==14.1.0
|
|
35
36
|
Requires-Dist: ruff>=0.11.11
|
|
36
37
|
Requires-Dist: tenacity>=8.2.0
|
|
38
|
+
Requires-Dist: termflow-md>=0.1.6
|
|
37
39
|
Requires-Dist: uvicorn>=0.30.0
|
|
38
40
|
Description-Content-Type: text/markdown
|
|
39
41
|
|
|
@@ -106,12 +108,7 @@ uvx code-puppy -i
|
|
|
106
108
|
# Install UV if you don't have it
|
|
107
109
|
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
108
110
|
|
|
109
|
-
|
|
110
|
-
echo 'export UV_MANAGED_PYTHON=1' >> ~/.zshrc # or ~/.bashrc
|
|
111
|
-
source ~/.zshrc # or ~/.bashrc
|
|
112
|
-
|
|
113
|
-
# Install and run code-puppy
|
|
114
|
-
uvx code-puppy -i
|
|
111
|
+
uvx code-puppy
|
|
115
112
|
```
|
|
116
113
|
|
|
117
114
|
#### Windows
|
|
@@ -122,73 +119,15 @@ On Windows, we recommend installing code-puppy as a global tool for the best exp
|
|
|
122
119
|
# Install UV if you don't have it (run in PowerShell as Admin)
|
|
123
120
|
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
124
121
|
|
|
125
|
-
|
|
126
|
-
uv tool install code-puppy
|
|
127
|
-
|
|
128
|
-
# Run code-puppy
|
|
129
|
-
code-puppy -i
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
**Why `uv tool install` on Windows?** Running with `uvx` creates an extra process layer that can interfere with keyboard signal handling (Ctrl+C, Ctrl+X). Installing as a tool runs code-puppy directly for reliable cancellation.
|
|
133
|
-
|
|
134
|
-
#### Upgrading
|
|
135
|
-
|
|
136
|
-
```bash
|
|
137
|
-
# Upgrade code-puppy to the latest version
|
|
138
|
-
uv tool upgrade code-puppy
|
|
139
|
-
|
|
140
|
-
# Or upgrade all installed tools
|
|
141
|
-
uv tool upgrade --all
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
UV will automatically download the latest compatible Python version (3.11+) if your system doesn't have one.
|
|
145
|
-
|
|
146
|
-
### pip (Alternative)
|
|
147
|
-
|
|
148
|
-
```bash
|
|
149
|
-
pip install code-puppy
|
|
122
|
+
uvx code-puppy
|
|
150
123
|
```
|
|
151
124
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
### Permanent Python Management
|
|
155
|
-
|
|
156
|
-
To make UV always use managed Python versions (recommended):
|
|
157
|
-
|
|
158
|
-
```bash
|
|
159
|
-
# Set environment variable permanently
|
|
160
|
-
echo 'export UV_MANAGED_PYTHON=1' >> ~/.zshrc # or ~/.bashrc
|
|
161
|
-
source ~/.zshrc # or ~/.bashrc
|
|
162
|
-
|
|
163
|
-
# Now all UV commands will prefer managed Python installations
|
|
164
|
-
uvx code-puppy # No need for --managed-python flag anymore
|
|
165
|
-
```
|
|
125
|
+
## Changelog (By Kittylog!)
|
|
166
126
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
# Check which Python UV will use
|
|
171
|
-
uv python find
|
|
172
|
-
|
|
173
|
-
# Or check the current project's Python
|
|
174
|
-
uv run python --version
|
|
175
|
-
```
|
|
127
|
+
[📋 View the full changelog on Kittylog](https://kittylog.app/c/mpfaffenberger/code_puppy)
|
|
176
128
|
|
|
177
129
|
## Usage
|
|
178
130
|
|
|
179
|
-
### Custom Commands
|
|
180
|
-
Create markdown files in `.claude/commands/`, `.github/prompts/`, or `.agents/commands/` to define custom slash commands. The filename becomes the command name and the content runs as a prompt.
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
# Create a custom command
|
|
184
|
-
echo "# Code Review
|
|
185
|
-
|
|
186
|
-
Please review this code for security issues." > .claude/commands/review.md
|
|
187
|
-
|
|
188
|
-
# Use it in Code Puppy
|
|
189
|
-
/review with focus on authentication
|
|
190
|
-
```
|
|
191
|
-
|
|
192
131
|
### Adding Models from models.dev 🆕
|
|
193
132
|
|
|
194
133
|
While there are several models configured right out of the box from providers like Synthetic, Cerebras, OpenAI, Google, and Anthropic, Code Puppy integrates with [models.dev](https://models.dev) to let you browse and add models from **65+ providers** with a single command:
|
|
@@ -256,6 +195,18 @@ The following environment variables control DBOS behavior:
|
|
|
256
195
|
- `DBOS_SYSTEM_DATABASE_URL`: Database URL used by DBOS. Can point to a local SQLite file or a Postgres instance. Example: `postgresql://postgres:dbos@localhost:5432/postgres`. Default: `dbos_store.sqlite` file in the config directory.
|
|
257
196
|
- `DBOS_APP_VERSION`: If set, Code Puppy uses it as the [DBOS application version](https://docs.dbos.dev/architecture#application-and-workflow-versions) and automatically tries to recover pending workflows for this version. Default: Code Puppy version + Unix timestamp in millisecond (disable automatic recovery).
|
|
258
197
|
|
|
198
|
+
### Custom Commands
|
|
199
|
+
Create markdown files in `.claude/commands/`, `.github/prompts/`, or `.agents/commands/` to define custom slash commands. The filename becomes the command name and the content runs as a prompt.
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# Create a custom command
|
|
203
|
+
echo "# Code Review
|
|
204
|
+
|
|
205
|
+
Please review this code for security issues." > .claude/commands/review.md
|
|
206
|
+
|
|
207
|
+
# Use it in Code Puppy
|
|
208
|
+
/review with focus on authentication
|
|
209
|
+
```
|
|
259
210
|
|
|
260
211
|
## Requirements
|
|
261
212
|
|
|
@@ -275,9 +226,6 @@ For examples and more information about agent rules, visit [https://agent.md](ht
|
|
|
275
226
|
|
|
276
227
|
Use the `/mcp` command to manage MCP (list, start, stop, status, etc.)
|
|
277
228
|
|
|
278
|
-
Watch this video for examples! https://www.youtube.com/watch?v=1t1zEetOqlo
|
|
279
|
-
|
|
280
|
-
|
|
281
229
|
## Round Robin Model Distribution
|
|
282
230
|
|
|
283
231
|
Code Puppy supports **Round Robin model distribution** to help you overcome rate limits and distribute load across multiple AI models. This feature automatically cycles through configured models with each request, maximizing your API usage while staying within rate limits.
|
|
@@ -2,17 +2,17 @@ code_puppy/__init__.py,sha256=xMPewo9RNHb3yfFNIk5WCbv2cvSPtJOCgK2-GqLbNnU,373
|
|
|
2
2
|
code_puppy/__main__.py,sha256=pDVssJOWP8A83iFkxMLY9YteHYat0EyWDQqMkKHpWp4,203
|
|
3
3
|
code_puppy/callbacks.py,sha256=hqTV--dNxG5vwWWm3MrEjmb8MZuHFFdmHePl23NXPHk,8621
|
|
4
4
|
code_puppy/chatgpt_codex_client.py,sha256=Om0ANB_kpHubhCwNzF9ENf8RvKBqs0IYzBLl_SNw0Vk,9833
|
|
5
|
-
code_puppy/claude_cache_client.py,sha256=
|
|
6
|
-
code_puppy/cli_runner.py,sha256=
|
|
5
|
+
code_puppy/claude_cache_client.py,sha256=MLIRSJP428r9IK_aV6XyCXrCfQnNti32U60psPymLM4,14860
|
|
6
|
+
code_puppy/cli_runner.py,sha256=BQu5Sa9y_ueqtgvbmuhWS-Tmd1FAjMbhTrtjFKbVZjM,34919
|
|
7
7
|
code_puppy/config.py,sha256=RlnrLkyFXm7h2Htf8rQA7vqoAyzLPMrESle417uLmFw,52373
|
|
8
8
|
code_puppy/error_logging.py,sha256=a80OILCUtJhexI6a9GM-r5LqIdjvSRzggfgPp2jv1X0,3297
|
|
9
9
|
code_puppy/gemini_code_assist.py,sha256=KGS7sO5OLc83nDF3xxS-QiU6vxW9vcm6hmzilu79Ef8,13867
|
|
10
|
-
code_puppy/http_utils.py,sha256=
|
|
10
|
+
code_puppy/http_utils.py,sha256=H3N5Qz2B1CcsGUYOycGWAqoNMr2P1NCVluKX3aRwRqI,10358
|
|
11
11
|
code_puppy/keymap.py,sha256=IvMkTlB_bIqOWpbTpmftkdyjhtD5todXuEIw1zCZ4u0,3584
|
|
12
12
|
code_puppy/main.py,sha256=82r3vZy_XcyEsenLn82BnUusaoyL3Bpm_Th_jKgqecE,273
|
|
13
|
-
code_puppy/model_factory.py,sha256=
|
|
13
|
+
code_puppy/model_factory.py,sha256=BSGHZlwtF7jkYz2qFG9oJglG-NnfmbsQXbx4I6stXW0,38313
|
|
14
14
|
code_puppy/model_utils.py,sha256=NU8W8NW5F7QS_PXHaLeh55Air1koUV7IVYFP7Rz3XpY,3615
|
|
15
|
-
code_puppy/models.json,sha256=
|
|
15
|
+
code_puppy/models.json,sha256=FMQdE_yvP_8y0xxt3K918UkFL9cZMYAqW1SfXcQkU_k,3105
|
|
16
16
|
code_puppy/models_dev_api.json,sha256=wHjkj-IM_fx1oHki6-GqtOoCrRMR0ScK0f-Iz0UEcy8,548187
|
|
17
17
|
code_puppy/models_dev_parser.py,sha256=8ndmWrsSyKbXXpRZPXc0w6TfWMuCcgaHiMifmlaBaPc,20611
|
|
18
18
|
code_puppy/pydantic_patches.py,sha256=YecAEeCOjSIwIBu2O5vEw72atMSL37cXGrbEuukI07o,4582
|
|
@@ -21,7 +21,7 @@ code_puppy/round_robin_model.py,sha256=kSawwPUiPgg0yg8r4AAVgvjzsWkptxpSORd75-HP7
|
|
|
21
21
|
code_puppy/session_storage.py,sha256=T4hOsAl9z0yz2JZCptjJBOnN8fCmkLZx5eLy1hTdv6Q,9631
|
|
22
22
|
code_puppy/status_display.py,sha256=qHzIQGAPEa2_-4gQSg7_rE1ihOosBq8WO73MWFNmmlo,8938
|
|
23
23
|
code_puppy/summarization_agent.py,sha256=6Pu_Wp_rF-HAhoX9u2uXTabRVkOZUYwRoMP1lzNS4ew,4485
|
|
24
|
-
code_puppy/terminal_utils.py,sha256=
|
|
24
|
+
code_puppy/terminal_utils.py,sha256=TaS19x7EZqudlBUAQwLMzBMNxBHBNInvQQREXqRGtkM,12984
|
|
25
25
|
code_puppy/uvx_detection.py,sha256=tP9X9Nvzow--KIqtqjgrHQkSxMJ3EevfoaeoB9VLY2o,7224
|
|
26
26
|
code_puppy/version_checker.py,sha256=aq2Mwxl1CR9sEFBgrPt3OQOowLOBUp9VaQYWJhuUv8Q,1780
|
|
27
27
|
code_puppy/agents/__init__.py,sha256=PtPB7Z5MSwmUKipgt_qxvIuGggcuVaYwNbnp1UP4tPc,518
|
|
@@ -40,18 +40,19 @@ code_puppy/agents/agent_qa_expert.py,sha256=5Ikb4U3SZQknUEfwlHZiyZXKqnffnOTQagr_
|
|
|
40
40
|
code_puppy/agents/agent_qa_kitten.py,sha256=5PeFFSwCFlTUvP6h5bGntx0xv5NmRwBiw0HnMqY8nLI,9107
|
|
41
41
|
code_puppy/agents/agent_security_auditor.py,sha256=SpiYNA0XAsIwBj7S2_EQPRslRUmF_-b89pIJyW7DYtY,12022
|
|
42
42
|
code_puppy/agents/agent_typescript_reviewer.py,sha256=vsnpp98xg6cIoFAEJrRTUM_i4wLEWGm5nJxs6fhHobM,10275
|
|
43
|
-
code_puppy/agents/base_agent.py,sha256=
|
|
43
|
+
code_puppy/agents/base_agent.py,sha256=QnPmROIw-rs5wopcVTZdBZusP0mGRC6EFZ7y_V00rMI,84825
|
|
44
44
|
code_puppy/agents/json_agent.py,sha256=lhopDJDoiSGHvD8A6t50hi9ZBoNRKgUywfxd0Po_Dzc,4886
|
|
45
45
|
code_puppy/agents/prompt_reviewer.py,sha256=JJrJ0m5q0Puxl8vFsyhAbY9ftU9n6c6UxEVdNct1E-Q,5558
|
|
46
46
|
code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
|
|
47
47
|
code_puppy/command_line/add_model_menu.py,sha256=caXxSQc6dgx0qQ68RRFrDTsiH-wZjl4nUv2r0javhaM,43262
|
|
48
48
|
code_puppy/command_line/attachments.py,sha256=4Q5I2Es4j0ltnz5wjw2z0QXMsiMJvEfWRkPf_lJeITM,13093
|
|
49
|
-
code_puppy/command_line/autosave_menu.py,sha256=
|
|
49
|
+
code_puppy/command_line/autosave_menu.py,sha256=de7nOmFmEH6x5T7C95U8N8xgxxeF-l5lgaJzGJsF3ZY,19824
|
|
50
|
+
code_puppy/command_line/clipboard.py,sha256=oe9bfAX5RnT81FiYrDmhvHaePS1tAT-NFG1fSXubSD4,16869
|
|
50
51
|
code_puppy/command_line/colors_menu.py,sha256=LoFVfJ-Mo-Eq9hnb2Rj5mn7oBCnadAGr-8NNHsHlu18,17273
|
|
51
52
|
code_puppy/command_line/command_handler.py,sha256=CY9F27eovZJK_kpU1YmbroYLWGTCuouCOQ-TXfDp-nw,10916
|
|
52
53
|
code_puppy/command_line/command_registry.py,sha256=qFySsw1g8dol3kgi0p6cXrIDlP11_OhOoaQ5nAadWXg,4416
|
|
53
54
|
code_puppy/command_line/config_commands.py,sha256=qS9Cm758DPz2QGvHLhAV4Tp_Xfgo3PyoCoLDusbnmCw,25742
|
|
54
|
-
code_puppy/command_line/core_commands.py,sha256=
|
|
55
|
+
code_puppy/command_line/core_commands.py,sha256=ujAPD4yDbXwYGJJfR2u4ei24eBV-Ps_-BVBjFMEoJy0,27668
|
|
55
56
|
code_puppy/command_line/diff_menu.py,sha256=_Gr9SP9fbItk-08dya9WTAR53s_PlyAvEnbt-8VWKPk,24141
|
|
56
57
|
code_puppy/command_line/file_path_completion.py,sha256=gw8NpIxa6GOpczUJRyh7VNZwoXKKn-yvCqit7h2y6Gg,2931
|
|
57
58
|
code_puppy/command_line/load_context_completion.py,sha256=a3JvLDeLLSYxVgTjAdqWzS4spjv6ccCrK2LKZgVJ1IM,2202
|
|
@@ -62,7 +63,7 @@ code_puppy/command_line/motd.py,sha256=XuIk3UTLawwVFM-NfoaJGU5F2hPLASTFXq84UdDMT
|
|
|
62
63
|
code_puppy/command_line/onboarding_slides.py,sha256=tHob7rB_n32dfjtPH-RSG0WLMjDHhlmNxfsF7WCgcVc,7191
|
|
63
64
|
code_puppy/command_line/onboarding_wizard.py,sha256=U5lV_1P3IwDYZUHar0zKgdp121zzkvOwwORvdCZwFcw,10241
|
|
64
65
|
code_puppy/command_line/pin_command_completion.py,sha256=juSvdqRpk7AdfkPy1DJx5NzfEUU5KYGlChvP0hisM18,11667
|
|
65
|
-
code_puppy/command_line/prompt_toolkit_completion.py,sha256=
|
|
66
|
+
code_puppy/command_line/prompt_toolkit_completion.py,sha256=U6rRMU3gNqTf3vz3K5V5PZ1xjE8I2ldoEk2FiT8kHJg,32535
|
|
66
67
|
code_puppy/command_line/session_commands.py,sha256=Jh8GGfhlfBAEVfucKLbcZjNaXYd0twImiOwq2ZnGdQQ,9902
|
|
67
68
|
code_puppy/command_line/utils.py,sha256=7eyxDHjPjPB9wGDJQQcXV_zOsGdYsFgI0SGCetVmTqE,1251
|
|
68
69
|
code_puppy/command_line/mcp/__init__.py,sha256=0-OQuwjq_pLiTVJ1_NrirVwdRerghyKs_MTZkwPC7YY,315
|
|
@@ -98,7 +99,7 @@ code_puppy/mcp_/config_wizard.py,sha256=JNNpgnSD6PFSyS3pTdEdD164oXd2VKp4VHLSz3To
|
|
|
98
99
|
code_puppy/mcp_/dashboard.py,sha256=VtaFxLtPnbM_HL2TXRDAg6IqcM-EcFkoghGgkfhMrKI,9417
|
|
99
100
|
code_puppy/mcp_/error_isolation.py,sha256=mpPBiH17zTXPsOEAn9WmkbwQwnt4gmgiaWv87JBJbUo,12426
|
|
100
101
|
code_puppy/mcp_/health_monitor.py,sha256=n5R6EeYOYbUucUFe74qGWCU3g6Mep5UEQbLF0wbT0dU,19688
|
|
101
|
-
code_puppy/mcp_/managed_server.py,sha256=
|
|
102
|
+
code_puppy/mcp_/managed_server.py,sha256=APqFKjHtsG8iM4so1dYxvKnb0BTmppHnaY8UJ5DBE9g,14075
|
|
102
103
|
code_puppy/mcp_/manager.py,sha256=pJ4cALicTxfwG2JIjJraLLf0Mzes-cEVAKIcUwfOoKA,29172
|
|
103
104
|
code_puppy/mcp_/mcp_logs.py,sha256=o4pSHwELWIjEjqhfaMMEGrBvb159-VIgUp21E707BPo,6264
|
|
104
105
|
code_puppy/mcp_/registry.py,sha256=U_t12WQ-En-KGyZoiTYdqlhp9NkDTWafu8g5InvF2NM,15774
|
|
@@ -112,10 +113,10 @@ code_puppy/messaging/bus.py,sha256=TbdltJ0D5tqnaE4irq1fcXllDYm-mQ_SiX1IFm-S4sw,2
|
|
|
112
113
|
code_puppy/messaging/commands.py,sha256=77CtKVNaF5KS3Xyzd0ccDAisZWQxL3weVEt3J-SfYxo,5464
|
|
113
114
|
code_puppy/messaging/markdown_patches.py,sha256=dMIJozzJChuHa8QNMSEz_kC-dyt7kZiDLZ7rjthbcmg,1626
|
|
114
115
|
code_puppy/messaging/message_queue.py,sha256=e-viZxacBoNSxRJnCJ4hU4vzsSI3oX_rN58RwhJKFfU,11825
|
|
115
|
-
code_puppy/messaging/messages.py,sha256=
|
|
116
|
+
code_puppy/messaging/messages.py,sha256=F7RwMHeQrIk-8kuSSBU76wBq1NGuLb2H5cJrSMTC3XM,16464
|
|
116
117
|
code_puppy/messaging/queue_console.py,sha256=T0U_V1tdN6hd9DLokp-HCk0mhu8Ivpfajha368CBZrU,9983
|
|
117
118
|
code_puppy/messaging/renderers.py,sha256=GHVtMnxE1pJ-yrcRjacY81JcjlHRz3UVHzp-ohN-CGE,12058
|
|
118
|
-
code_puppy/messaging/rich_renderer.py,sha256=
|
|
119
|
+
code_puppy/messaging/rich_renderer.py,sha256=FiT1e5S8nNQte0E6CMFQ3KyTixadkgKSjp1hcZXtyOE,37892
|
|
119
120
|
code_puppy/messaging/spinner/__init__.py,sha256=KpK5tJqq9YnN3wklqvdH0BQmuwYnT83Mp4tPfQa9RqI,1664
|
|
120
121
|
code_puppy/messaging/spinner/console_spinner.py,sha256=YIReuWPD01YPy58FqWdMDWj2QhauTUxKo675Ub4-eDA,8451
|
|
121
122
|
code_puppy/messaging/spinner/spinner_base.py,sha256=JiQDAhCfwrWUFunb8Xcj1caEl34JJY7Bcio7mDeckSc,2694
|
|
@@ -123,7 +124,7 @@ code_puppy/plugins/__init__.py,sha256=gWgrXWoFpl-3Mxz2DAvxKW6SkCWrOnw-hKsY9O7nHc
|
|
|
123
124
|
code_puppy/plugins/oauth_puppy_html.py,sha256=Wpa-V_NlRiBAvo_OXHuR7wvOH_jSt8L9HSFGiab6xI0,13058
|
|
124
125
|
code_puppy/plugins/antigravity_oauth/__init__.py,sha256=1miHihSqRNXO20Vh_Gn9M3Aa2szh0gtdSCaKKj9nq0Q,362
|
|
125
126
|
code_puppy/plugins/antigravity_oauth/accounts.py,sha256=GQit2-K24bsopmTZyscFUq3M0cAEO5WutHWnipVdgz8,14304
|
|
126
|
-
code_puppy/plugins/antigravity_oauth/antigravity_model.py,sha256=
|
|
127
|
+
code_puppy/plugins/antigravity_oauth/antigravity_model.py,sha256=g0_nXnMg288CvBE48CFgZ-iAqlYbtbi1dcB4Up6cYYc,26115
|
|
127
128
|
code_puppy/plugins/antigravity_oauth/config.py,sha256=BoQgqf5I2XoHWnBBo9vhCIc_XwPj9Mbp0Z95ygWwt78,1362
|
|
128
129
|
code_puppy/plugins/antigravity_oauth/constants.py,sha256=qsrA10JJvzNuY0OobvvwCQcoGpILBninllcUUMKkUrQ,4644
|
|
129
130
|
code_puppy/plugins/antigravity_oauth/oauth.py,sha256=ZHXJtZP63l6brOpX1WdLfuUClIleA79-4y36YUJc6Wo,15137
|
|
@@ -145,7 +146,7 @@ code_puppy/plugins/claude_code_oauth/__init__.py,sha256=mCcOU-wM7LNCDjr-w-WLPzom
|
|
|
145
146
|
code_puppy/plugins/claude_code_oauth/config.py,sha256=DjGySCkvjSGZds6DYErLMAi3TItt8iSLGvyJN98nSEM,2013
|
|
146
147
|
code_puppy/plugins/claude_code_oauth/register_callbacks.py,sha256=g8sl-i7jIOF6OFALeaLqTF3mS4tD8GR_FCzvPjVw2js,10165
|
|
147
148
|
code_puppy/plugins/claude_code_oauth/test_plugin.py,sha256=yQy4EeZl4bjrcog1d8BjknoDTRK75mRXXvkSQJYSSEM,9286
|
|
148
|
-
code_puppy/plugins/claude_code_oauth/utils.py,sha256=
|
|
149
|
+
code_puppy/plugins/claude_code_oauth/utils.py,sha256=TVgz5aFd2GFPHSiG9NnOYiw-y6KRkWwt_SZxmMpwMIY,17243
|
|
149
150
|
code_puppy/plugins/customizable_commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
150
151
|
code_puppy/plugins/customizable_commands/register_callbacks.py,sha256=zVMfIzr--hVn0IOXxIicbmgj2s-HZUgtrOc0NCDOnDw,5183
|
|
151
152
|
code_puppy/plugins/example_custom_command/README.md,sha256=5c5Zkm7CW6BDSfe3WoLU7GW6t5mjjYAbu9-_pu-b3p4,8244
|
|
@@ -159,8 +160,8 @@ code_puppy/plugins/shell_safety/register_callbacks.py,sha256=W3v664RR48Fdbbbltf_
|
|
|
159
160
|
code_puppy/prompts/codex_system_prompt.md,sha256=hEFTCziroLqZmqNle5kG34A8kvTteOWezCiVrAEKhE0,24400
|
|
160
161
|
code_puppy/tools/__init__.py,sha256=BVTZ85jLHgDANwOnUSOz3UDlp8VQDq4DoGF23BRlyWw,6032
|
|
161
162
|
code_puppy/tools/agent_tools.py,sha256=snBI6FlFtR03CbYKXwu53R48c_fRSuDIwcNdVUruLcA,21020
|
|
162
|
-
code_puppy/tools/command_runner.py,sha256=
|
|
163
|
-
code_puppy/tools/common.py,sha256=
|
|
163
|
+
code_puppy/tools/command_runner.py,sha256=3qXVnVTaBPia6y2D29As47_TRKgpyCj82yMFK-8UUYc,44954
|
|
164
|
+
code_puppy/tools/common.py,sha256=IYf-KOcP5eN2MwTlpULSXNATn7GzloAKl7_M1Uyfe4Y,40360
|
|
164
165
|
code_puppy/tools/file_modifications.py,sha256=vz9n7R0AGDSdLUArZr_55yJLkyI30M8zreAppxIx02M,29380
|
|
165
166
|
code_puppy/tools/file_operations.py,sha256=CqhpuBnOFOcQCIYXOujskxq2VMLWYJhibYrH0YcPSfA,35692
|
|
166
167
|
code_puppy/tools/tools_content.py,sha256=bsBqW-ppd1XNAS_g50B3UHDQBWEALC1UneH6-afz1zo,2365
|
|
@@ -174,10 +175,10 @@ code_puppy/tools/browser/browser_scripts.py,sha256=sNb8eLEyzhasy5hV4B9OjM8yIVMLV
|
|
|
174
175
|
code_puppy/tools/browser/browser_workflows.py,sha256=nitW42vCf0ieTX1gLabozTugNQ8phtoFzZbiAhw1V90,6491
|
|
175
176
|
code_puppy/tools/browser/camoufox_manager.py,sha256=RZjGOEftE5sI_tsercUyXFSZI2wpStXf-q0PdYh2G3I,8680
|
|
176
177
|
code_puppy/tools/browser/vqa_agent.py,sha256=DBn9HKloILqJSTSdNZzH_PYWT0B2h9VwmY6akFQI_uU,2913
|
|
177
|
-
code_puppy-0.0.
|
|
178
|
-
code_puppy-0.0.
|
|
179
|
-
code_puppy-0.0.
|
|
180
|
-
code_puppy-0.0.
|
|
181
|
-
code_puppy-0.0.
|
|
182
|
-
code_puppy-0.0.
|
|
183
|
-
code_puppy-0.0.
|
|
178
|
+
code_puppy-0.0.341.data/data/code_puppy/models.json,sha256=FMQdE_yvP_8y0xxt3K918UkFL9cZMYAqW1SfXcQkU_k,3105
|
|
179
|
+
code_puppy-0.0.341.data/data/code_puppy/models_dev_api.json,sha256=wHjkj-IM_fx1oHki6-GqtOoCrRMR0ScK0f-Iz0UEcy8,548187
|
|
180
|
+
code_puppy-0.0.341.dist-info/METADATA,sha256=TyW2aMaB5pukc2EP2CV8fjW-qotBUDUms_CeaiUbKv4,27550
|
|
181
|
+
code_puppy-0.0.341.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
182
|
+
code_puppy-0.0.341.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
|
|
183
|
+
code_puppy-0.0.341.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
184
|
+
code_puppy-0.0.341.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|