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.
@@ -7,28 +7,25 @@ import os
7
7
 
8
8
  MOTD_VERSION = "20250815"
9
9
  MOTD_MESSAGE = """
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 |
17
- | (obviously), but it's still good for basic fetches. |
18
- | 2. We also added support for OpenAI gpt-5! |
19
- | It's so good, it'll make you want to teach it to sit!|
20
- | |
21
- | To use one of the Cerebras models just have a |
22
- | CEREBRAS_API_KEY set in the environment variables. |
23
- | Use ~m to swap models in the middle of your session! |
24
- | Take stretch breaks you'll need 'em! |
25
- | • DRY your code, but keep your pup hydrated. |
26
- | • If you hit a bug, treat yourself for finding it! |
27
- | |
28
- | Today: sniff, code, roll over, and let these fancy AI |
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
 
@@ -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
- client = httpx.AsyncClient(headers=headers, verify=ca_certs_path)
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
- client = httpx.AsyncClient(headers=headers, verify=ca_certs_path)
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.79
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=P2E3KgTHMVaMhHyGHmdascjYmdRxUKBWotlP61i-03A,8291
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=0G6_BHLiIdONNVMxlvmTJFh5j7CvnIX530JlUPD5SDE,2323
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.79.data/data/code_puppy/models.json,sha256=hqSvFzSPcwxMwst6xePlcppm0c_pjyEVSBsWvgbAG98,2714
26
- code_puppy-0.0.79.dist-info/METADATA,sha256=NWi6a8SKiYPdoAetPAHd4bJ08ouT120WRSCryz3Fb1g,6643
27
- code_puppy-0.0.79.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
28
- code_puppy-0.0.79.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
29
- code_puppy-0.0.79.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
30
- code_puppy-0.0.79.dist-info/RECORD,,
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,,