code-puppy 0.0.79__py3-none-any.whl → 0.0.81__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/command_line/motd.py +19 -22
- code_puppy/model_factory.py +74 -2
- {code_puppy-0.0.79.dist-info → code_puppy-0.0.81.dist-info}/METADATA +6 -1
- {code_puppy-0.0.79.dist-info → code_puppy-0.0.81.dist-info}/RECORD +8 -8
- {code_puppy-0.0.79.data → code_puppy-0.0.81.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.79.dist-info → code_puppy-0.0.81.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.79.dist-info → code_puppy-0.0.81.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.79.dist-info → code_puppy-0.0.81.dist-info}/licenses/LICENSE +0 -0
code_puppy/command_line/motd.py
CHANGED
|
@@ -7,28 +7,25 @@ import os
|
|
|
7
7
|
|
|
8
8
|
MOTD_VERSION = "20250815"
|
|
9
9
|
MOTD_MESSAGE = """
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
| models do the heavy lifting. Fire up a ~motd anytime |
|
|
30
|
-
| you need some puppy hype! |
|
|
31
|
-
\___________________________________________________________/
|
|
10
|
+
|
|
11
|
+
🐾 Happy Friday, Aug 15, 2025!
|
|
12
|
+
|
|
13
|
+
Biscuit the code puppy is on full zoomie mode!
|
|
14
|
+
Major paws-ups:
|
|
15
|
+
1. We now integrate Cerebras gpt-oss-120b!
|
|
16
|
+
It's a bit underwhelming compared to Qwen3-Coder-480b (obviously), but it's still good for basic fetches.
|
|
17
|
+
2. We also added support for OpenAI gpt-5!
|
|
18
|
+
It's so good, it'll make you want to teach it to sit!
|
|
19
|
+
|
|
20
|
+
• To use one of the Cerebras models just have a CEREBRAS_API_KEY set in the environment variables.
|
|
21
|
+
• Use ~m to swap models in the middle of your session!
|
|
22
|
+
• Take stretch breaks – you'll need 'em!
|
|
23
|
+
• DRY your code, but keep your pup hydrated.
|
|
24
|
+
• If you hit a bug, treat yourself for finding it!
|
|
25
|
+
|
|
26
|
+
Today: sniff, code, roll over, and let these fancy AI models do the heavy lifting. Fire up a ~motd anytime
|
|
27
|
+
you need some puppy hype!
|
|
28
|
+
|
|
32
29
|
"""
|
|
33
30
|
MOTD_TRACK_FILE = os.path.expanduser("~/.puppy_cfg/motd.txt")
|
|
34
31
|
|
code_puppy/model_factory.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
+
import random
|
|
3
4
|
from typing import Any, Dict
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
@@ -13,6 +14,8 @@ from pydantic_ai.providers.google_gla import GoogleGLAProvider
|
|
|
13
14
|
from pydantic_ai.providers.openai import OpenAIProvider
|
|
14
15
|
from pydantic_ai.providers.openrouter import OpenRouterProvider
|
|
15
16
|
|
|
17
|
+
from code_puppy.tools.common import console
|
|
18
|
+
|
|
16
19
|
# Environment variables used in this module:
|
|
17
20
|
# - GEMINI_API_KEY: API key for Google's Gemini models. Required when using Gemini models.
|
|
18
21
|
# - OPENAI_API_KEY: API key for OpenAI models. Required when using OpenAI models or custom_openai endpoints.
|
|
@@ -23,6 +26,53 @@ from pydantic_ai.providers.openrouter import OpenRouterProvider
|
|
|
23
26
|
# Example: "X-Api-Key": "$OPENAI_API_KEY" will use the value from os.environ.get("OPENAI_API_KEY")
|
|
24
27
|
|
|
25
28
|
|
|
29
|
+
def build_proxy_dict(proxy):
|
|
30
|
+
proxy_tokens = proxy.split(":")
|
|
31
|
+
structure = "{}:{}@{}:{}".format(
|
|
32
|
+
proxy_tokens[2], proxy_tokens[3], proxy_tokens[0], proxy_tokens[1]
|
|
33
|
+
)
|
|
34
|
+
proxies = {
|
|
35
|
+
"http": "http://{}/".format(structure),
|
|
36
|
+
"https": "http://{}".format(structure),
|
|
37
|
+
}
|
|
38
|
+
return proxies
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def build_httpx_proxy(proxy):
|
|
42
|
+
"""Build an httpx.Proxy object from a proxy string in format ip:port:username:password"""
|
|
43
|
+
proxy_tokens = proxy.split(":")
|
|
44
|
+
if len(proxy_tokens) != 4:
|
|
45
|
+
raise ValueError(f"Invalid proxy format: {proxy}. Expected format: ip:port:username:password")
|
|
46
|
+
|
|
47
|
+
ip, port, username, password = proxy_tokens
|
|
48
|
+
proxy_url = f"http://{ip}:{port}"
|
|
49
|
+
proxy_auth = (username, password)
|
|
50
|
+
|
|
51
|
+
# Log the proxy being used
|
|
52
|
+
console.log(f"Using proxy: {proxy_url} with username: {username}")
|
|
53
|
+
|
|
54
|
+
return httpx.Proxy(url=proxy_url, auth=proxy_auth)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_random_proxy_from_file(file_path):
|
|
58
|
+
"""Reads proxy file and returns a random proxy formatted for httpx.AsyncClient"""
|
|
59
|
+
if not os.path.exists(file_path):
|
|
60
|
+
raise ValueError(f"Proxy file '{file_path}' not found.")
|
|
61
|
+
|
|
62
|
+
with open(file_path, "r") as f:
|
|
63
|
+
proxies = [line.strip() for line in f.readlines() if line.strip()]
|
|
64
|
+
|
|
65
|
+
if not proxies:
|
|
66
|
+
raise ValueError(f"Proxy file '{file_path}' is empty or contains only whitespace.")
|
|
67
|
+
|
|
68
|
+
selected_proxy = random.choice(proxies)
|
|
69
|
+
try:
|
|
70
|
+
return build_httpx_proxy(selected_proxy)
|
|
71
|
+
except ValueError as e:
|
|
72
|
+
console.log(f"Warning: Malformed proxy '{selected_proxy}' found in file '{file_path}', ignoring and continuing without proxy.")
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
|
|
26
76
|
def get_custom_config(model_config):
|
|
27
77
|
custom_config = model_config.get("custom_endpoint", {})
|
|
28
78
|
if not custom_config:
|
|
@@ -97,7 +147,18 @@ class ModelFactory:
|
|
|
97
147
|
|
|
98
148
|
elif model_type == "custom_anthropic":
|
|
99
149
|
url, headers, ca_certs_path, api_key = get_custom_config(model_config)
|
|
100
|
-
|
|
150
|
+
|
|
151
|
+
# Check for proxy configuration
|
|
152
|
+
proxy_file_path = os.environ.get("CODE_PUPPY_PROXIES")
|
|
153
|
+
proxy = None
|
|
154
|
+
if proxy_file_path:
|
|
155
|
+
proxy = get_random_proxy_from_file(proxy_file_path)
|
|
156
|
+
|
|
157
|
+
# Only pass proxy to client if it's valid
|
|
158
|
+
client_args = {"headers": headers, "verify": ca_certs_path}
|
|
159
|
+
if proxy is not None:
|
|
160
|
+
client_args["proxy"] = proxy
|
|
161
|
+
client = httpx.AsyncClient(**client_args)
|
|
101
162
|
anthropic_client = AsyncAnthropic(
|
|
102
163
|
base_url=url,
|
|
103
164
|
http_client=client,
|
|
@@ -162,7 +223,18 @@ class ModelFactory:
|
|
|
162
223
|
|
|
163
224
|
elif model_type == "custom_openai":
|
|
164
225
|
url, headers, ca_certs_path, api_key = get_custom_config(model_config)
|
|
165
|
-
|
|
226
|
+
|
|
227
|
+
# Check for proxy configuration
|
|
228
|
+
proxy_file_path = os.environ.get("CODE_PUPPY_PROXIES")
|
|
229
|
+
proxy = None
|
|
230
|
+
if proxy_file_path:
|
|
231
|
+
proxy = get_random_proxy_from_file(proxy_file_path)
|
|
232
|
+
|
|
233
|
+
# Only pass proxy to client if it's valid
|
|
234
|
+
client_args = {"headers": headers, "verify": ca_certs_path}
|
|
235
|
+
if proxy is not None:
|
|
236
|
+
client_args["proxy"] = proxy
|
|
237
|
+
client = httpx.AsyncClient(**client_args)
|
|
166
238
|
provider_args = dict(
|
|
167
239
|
base_url=url,
|
|
168
240
|
http_client=client,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.81
|
|
4
4
|
Summary: Code generation agent
|
|
5
5
|
Author: Michael Pfaffenberger
|
|
6
6
|
License: MIT
|
|
@@ -51,6 +51,11 @@ Description-Content-Type: text/markdown
|
|
|
51
51
|
|
|
52
52
|
Code Puppy is an AI-powered code generation agent, designed to understand programming tasks, generate high-quality code, and explain its reasoning similar to tools like Windsurf and Cursor.
|
|
53
53
|
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
`uvx code-puppy -i`
|
|
57
|
+
|
|
58
|
+
|
|
54
59
|
## Features
|
|
55
60
|
|
|
56
61
|
- **Multi-language support**: Capable of generating code in various programming languages.
|
|
@@ -4,7 +4,7 @@ code_puppy/agent_prompts.py,sha256=13YIpTZa3R3lg60-fdkll7t7hgSBtQL0M53wcE1gzyQ,6
|
|
|
4
4
|
code_puppy/config.py,sha256=r5nw5ChOP8xd_K5yo8U5OtO2gy2bFhARiyNtDp1JrwQ,5013
|
|
5
5
|
code_puppy/main.py,sha256=uKMG0WNrFjEbsiEb_OwL_fNJbqMyTgztGjPKIOoYdSs,10444
|
|
6
6
|
code_puppy/message_history_processor.py,sha256=NaFYEUdHCZlzl5jR-XK4Rh2EHVsupT-SROxe4jXgUaQ,2584
|
|
7
|
-
code_puppy/model_factory.py,sha256=
|
|
7
|
+
code_puppy/model_factory.py,sha256=3j7AcJfZAHbx_plL9oOxjGJO0MMTRaQFThCErg8VpH8,10909
|
|
8
8
|
code_puppy/models.json,sha256=hqSvFzSPcwxMwst6xePlcppm0c_pjyEVSBsWvgbAG98,2714
|
|
9
9
|
code_puppy/session_memory.py,sha256=4sgAAjbXdLSi8hETpd56tgtrG6hqMUuZWDlJOu6BQjA,2735
|
|
10
10
|
code_puppy/state_management.py,sha256=aymPVogToEeF_vPc2c75rs8WLYNd8s2vMRGNXvTriW0,1248
|
|
@@ -13,7 +13,7 @@ code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZ
|
|
|
13
13
|
code_puppy/command_line/file_path_completion.py,sha256=gw8NpIxa6GOpczUJRyh7VNZwoXKKn-yvCqit7h2y6Gg,2931
|
|
14
14
|
code_puppy/command_line/meta_command_handler.py,sha256=L7qP2g0Faz0V7bMH4YK3s03OWWuQFtK7Sh-Kt2zmmEQ,6182
|
|
15
15
|
code_puppy/command_line/model_picker_completion.py,sha256=NkyZZG7IhcVWSJ3ADytwCA5f8DpNeVs759Qtqs4fQtY,3733
|
|
16
|
-
code_puppy/command_line/motd.py,sha256=
|
|
16
|
+
code_puppy/command_line/motd.py,sha256=1qEPpEQb14XfEXj-_pmx7ad8VtzvP7JSmvvW_JWW-Os,1662
|
|
17
17
|
code_puppy/command_line/prompt_toolkit_completion.py,sha256=_gP0FIOgHDNHTTWLNL0XNzr6sO0ISe7Mec1uQNo9kcM,8337
|
|
18
18
|
code_puppy/command_line/utils.py,sha256=7eyxDHjPjPB9wGDJQQcXV_zOsGdYsFgI0SGCetVmTqE,1251
|
|
19
19
|
code_puppy/tools/__init__.py,sha256=ozIGpLM7pKSjH4UeojkTodhfVYZeNzMsLtK_oyw41HA,456
|
|
@@ -22,9 +22,9 @@ code_puppy/tools/common.py,sha256=M53zhiXZAmPdvi1Y_bzCxgvEmifOvRRJvYPARYRZqHw,22
|
|
|
22
22
|
code_puppy/tools/file_modifications.py,sha256=qCfkZ7BxTG8U4xydHzS44UtOioj8XvhRKgjoOAnMHTo,13310
|
|
23
23
|
code_puppy/tools/file_operations.py,sha256=5ESOCS3m4Lpnvrg2XiJAx0m4-0Yar6LZKIdyRCRjENM,11218
|
|
24
24
|
code_puppy/tools/ts_code_map.py,sha256=o-u8p5vsYwitfDtVEoPS-7MwWn2xHzwtIQLo1_WMhQs,17647
|
|
25
|
-
code_puppy-0.0.
|
|
26
|
-
code_puppy-0.0.
|
|
27
|
-
code_puppy-0.0.
|
|
28
|
-
code_puppy-0.0.
|
|
29
|
-
code_puppy-0.0.
|
|
30
|
-
code_puppy-0.0.
|
|
25
|
+
code_puppy-0.0.81.data/data/code_puppy/models.json,sha256=hqSvFzSPcwxMwst6xePlcppm0c_pjyEVSBsWvgbAG98,2714
|
|
26
|
+
code_puppy-0.0.81.dist-info/METADATA,sha256=d8xhiEpZU64TOZkRnAI5N28ql73s-i8ERXrNgwQlHDg,6681
|
|
27
|
+
code_puppy-0.0.81.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
28
|
+
code_puppy-0.0.81.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
|
|
29
|
+
code_puppy-0.0.81.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
30
|
+
code_puppy-0.0.81.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|