code-puppy 0.0.144__py3-none-any.whl → 0.0.146__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/agent.py +4 -3
- code_puppy/command_line/meta_command_handler.py +4 -4
- code_puppy/config.py +16 -2
- code_puppy/model_factory.py +4 -1
- code_puppy/round_robin_model.py +25 -6
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.146.dist-info}/METADATA +5 -2
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.146.dist-info}/RECORD +11 -11
- {code_puppy-0.0.144.data → code_puppy-0.0.146.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.146.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.146.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.144.dist-info → code_puppy-0.0.146.dist-info}/licenses/LICENSE +0 -0
code_puppy/agent.py
CHANGED
|
@@ -193,8 +193,9 @@ def get_code_generation_agent(force_reload=False, message_group: str | None = No
|
|
|
193
193
|
|
|
194
194
|
def get_custom_usage_limits():
|
|
195
195
|
"""
|
|
196
|
-
Returns custom usage limits with
|
|
196
|
+
Returns custom usage limits with configurable request limit.
|
|
197
197
|
This centralizes the configuration of rate limiting for the agent.
|
|
198
|
-
Default pydantic-ai limit is 50, this increases it to 100.
|
|
198
|
+
Default pydantic-ai limit is 50, this increases it to the configured value (default 100).
|
|
199
199
|
"""
|
|
200
|
-
|
|
200
|
+
from code_puppy.config import get_message_limit
|
|
201
|
+
return UsageLimits(request_limit=get_message_limit())
|
|
@@ -17,7 +17,7 @@ META_COMMANDS_HELP = """
|
|
|
17
17
|
~m <model> Set active model
|
|
18
18
|
~motd Show the latest message of the day (MOTD)
|
|
19
19
|
~show Show puppy config key-values
|
|
20
|
-
~set Set puppy config key-values
|
|
20
|
+
~set Set puppy config key-values (message_limit, protected_token_count, compaction_threshold, etc.)
|
|
21
21
|
~<unknown> Show unknown meta command warning
|
|
22
22
|
"""
|
|
23
23
|
|
|
@@ -62,21 +62,21 @@ def handle_meta_command(command: str, console: Console) -> bool:
|
|
|
62
62
|
get_owner_name,
|
|
63
63
|
get_puppy_name,
|
|
64
64
|
get_yolo_mode,
|
|
65
|
-
|
|
65
|
+
get_message_limit,
|
|
66
66
|
)
|
|
67
67
|
|
|
68
68
|
puppy_name = get_puppy_name()
|
|
69
69
|
owner_name = get_owner_name()
|
|
70
70
|
model = get_active_model()
|
|
71
71
|
yolo_mode = get_yolo_mode()
|
|
72
|
-
msg_limit =
|
|
72
|
+
msg_limit = get_message_limit()
|
|
73
73
|
console.print(f"""[bold magenta]🐶 Puppy Status[/bold magenta]
|
|
74
74
|
|
|
75
75
|
[bold]puppy_name:[/bold] [cyan]{puppy_name}[/cyan]
|
|
76
76
|
[bold]owner_name:[/bold] [cyan]{owner_name}[/cyan]
|
|
77
77
|
[bold]model:[/bold] [green]{model}[/green]
|
|
78
78
|
[bold]YOLO_MODE:[/bold] {"[red]ON[/red]" if yolo_mode else "[yellow]off[/yellow]"}
|
|
79
|
-
[bold]
|
|
79
|
+
[bold]message_limit:[/bold] [cyan]{msg_limit}[/cyan] requests per minute
|
|
80
80
|
""")
|
|
81
81
|
return True
|
|
82
82
|
|
code_puppy/config.py
CHANGED
|
@@ -93,9 +93,9 @@ def get_model_context_length() -> int:
|
|
|
93
93
|
def get_config_keys():
|
|
94
94
|
"""
|
|
95
95
|
Returns the list of all config keys currently in puppy.cfg,
|
|
96
|
-
plus certain preset expected keys (e.g. "yolo_mode", "model", "compaction_strategy").
|
|
96
|
+
plus certain preset expected keys (e.g. "yolo_mode", "model", "compaction_strategy", "message_limit").
|
|
97
97
|
"""
|
|
98
|
-
default_keys = ["yolo_mode", "model", "compaction_strategy"]
|
|
98
|
+
default_keys = ["yolo_mode", "model", "compaction_strategy", "message_limit"]
|
|
99
99
|
config = configparser.ConfigParser()
|
|
100
100
|
config.read(CONFIG_FILE)
|
|
101
101
|
keys = set(config[DEFAULT_SECTION].keys()) if DEFAULT_SECTION in config else set()
|
|
@@ -435,6 +435,20 @@ def get_compaction_strategy() -> str:
|
|
|
435
435
|
return "truncation"
|
|
436
436
|
|
|
437
437
|
|
|
438
|
+
def get_message_limit(default: int = 100) -> int:
|
|
439
|
+
"""
|
|
440
|
+
Returns the user-configured message/request limit for the agent.
|
|
441
|
+
This controls how many steps/requests the agent can take.
|
|
442
|
+
Defaults to 100 if unset or misconfigured.
|
|
443
|
+
Configurable by 'message_limit' key.
|
|
444
|
+
"""
|
|
445
|
+
val = get_value("message_limit")
|
|
446
|
+
try:
|
|
447
|
+
return int(val) if val else default
|
|
448
|
+
except (ValueError, TypeError):
|
|
449
|
+
return default
|
|
450
|
+
|
|
451
|
+
|
|
438
452
|
def save_command_to_history(command: str):
|
|
439
453
|
"""Save a command to the history file with an ISO format timestamp.
|
|
440
454
|
|
code_puppy/model_factory.py
CHANGED
|
@@ -255,6 +255,9 @@ class ModelFactory:
|
|
|
255
255
|
if not model_names or not isinstance(model_names, list):
|
|
256
256
|
raise ValueError(f"Round-robin model '{model_name}' requires a 'models' list in its configuration.")
|
|
257
257
|
|
|
258
|
+
# Get the rotate_every parameter (default: 1)
|
|
259
|
+
rotate_every = model_config.get("rotate_every", 1)
|
|
260
|
+
|
|
258
261
|
# Resolve each model name to an actual model instance
|
|
259
262
|
models = []
|
|
260
263
|
for name in model_names:
|
|
@@ -263,7 +266,7 @@ class ModelFactory:
|
|
|
263
266
|
models.append(model)
|
|
264
267
|
|
|
265
268
|
# Create and return the round-robin model
|
|
266
|
-
return RoundRobinModel(*models)
|
|
269
|
+
return RoundRobinModel(*models, rotate_every=rotate_every)
|
|
267
270
|
|
|
268
271
|
else:
|
|
269
272
|
raise ValueError(f"Unsupported model type: {model_type}")
|
code_puppy/round_robin_model.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
from contextlib import asynccontextmanager, suppress
|
|
2
3
|
from dataclasses import dataclass, field
|
|
3
4
|
from typing import Any, Callable, AsyncIterator, List
|
|
@@ -29,26 +30,39 @@ class RoundRobinModel(Model):
|
|
|
29
30
|
models: List[Model]
|
|
30
31
|
_current_index: int = field(default=0, repr=False)
|
|
31
32
|
_model_name: str = field(repr=False)
|
|
33
|
+
_rotate_every: int = field(default=1, repr=False)
|
|
34
|
+
_request_count: int = field(default=0, repr=False)
|
|
32
35
|
|
|
33
36
|
def __init__(
|
|
34
37
|
self,
|
|
35
|
-
*models: Model
|
|
38
|
+
*models: Model,
|
|
39
|
+
rotate_every: int = 1,
|
|
40
|
+
settings: ModelSettings | None = None
|
|
36
41
|
):
|
|
37
42
|
"""Initialize a round-robin model instance.
|
|
38
43
|
|
|
39
44
|
Args:
|
|
40
|
-
models: The
|
|
45
|
+
models: The model instances to cycle through.
|
|
46
|
+
rotate_every: Number of requests before rotating to the next model (default: 1).
|
|
47
|
+
settings: Model settings that will be used as defaults for this model.
|
|
41
48
|
"""
|
|
42
|
-
super().__init__()
|
|
49
|
+
super().__init__(settings=settings)
|
|
43
50
|
if not models:
|
|
44
51
|
raise ValueError("At least one model must be provided")
|
|
45
|
-
|
|
52
|
+
if rotate_every < 1:
|
|
53
|
+
raise ValueError("rotate_every must be at least 1")
|
|
54
|
+
self.models = list(models)
|
|
46
55
|
self._current_index = 0
|
|
56
|
+
self._request_count = 0
|
|
57
|
+
self._rotate_every = rotate_every
|
|
47
58
|
|
|
48
59
|
@property
|
|
49
60
|
def model_name(self) -> str:
|
|
50
61
|
"""The model name showing this is a round-robin model with its candidates."""
|
|
51
|
-
|
|
62
|
+
base_name = f'round_robin:{",".join(model.model_name for model in self.models)}'
|
|
63
|
+
if self._rotate_every != 1:
|
|
64
|
+
return f'{base_name}:rotate_every={self._rotate_every}'
|
|
65
|
+
return base_name
|
|
52
66
|
|
|
53
67
|
@property
|
|
54
68
|
def system(self) -> str:
|
|
@@ -63,7 +77,10 @@ class RoundRobinModel(Model):
|
|
|
63
77
|
def _get_next_model(self) -> Model:
|
|
64
78
|
"""Get the next model in the round-robin sequence and update the index."""
|
|
65
79
|
model = self.models[self._current_index]
|
|
66
|
-
self.
|
|
80
|
+
self._request_count += 1
|
|
81
|
+
if self._request_count >= self._rotate_every:
|
|
82
|
+
self._current_index = (self._current_index + 1) % len(self.models)
|
|
83
|
+
self._request_count = 0
|
|
67
84
|
return model
|
|
68
85
|
|
|
69
86
|
async def request(
|
|
@@ -74,6 +91,7 @@ class RoundRobinModel(Model):
|
|
|
74
91
|
) -> ModelResponse:
|
|
75
92
|
"""Make a request using the next model in the round-robin sequence."""
|
|
76
93
|
current_model = self._get_next_model()
|
|
94
|
+
# Use the current model's settings as base, then merge with provided settings
|
|
77
95
|
merged_settings = merge_model_settings(current_model.settings, model_settings)
|
|
78
96
|
customized_model_request_parameters = current_model.customize_request_parameters(model_request_parameters)
|
|
79
97
|
|
|
@@ -96,6 +114,7 @@ class RoundRobinModel(Model):
|
|
|
96
114
|
) -> AsyncIterator[StreamedResponse]:
|
|
97
115
|
"""Make a streaming request using the next model in the round-robin sequence."""
|
|
98
116
|
current_model = self._get_next_model()
|
|
117
|
+
# Use the current model's settings as base, then merge with provided settings
|
|
99
118
|
merged_settings = merge_model_settings(current_model.settings, model_settings)
|
|
100
119
|
customized_model_request_parameters = current_model.customize_request_parameters(model_request_parameters)
|
|
101
120
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.146
|
|
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
|
|
@@ -234,13 +234,16 @@ export CEREBRAS_API_KEY3=csk-...
|
|
|
234
234
|
},
|
|
235
235
|
"cerebras_round_robin": {
|
|
236
236
|
"type": "round_robin",
|
|
237
|
-
"models": ["qwen1", "qwen2", "qwen3"]
|
|
237
|
+
"models": ["qwen1", "qwen2", "qwen3"],
|
|
238
|
+
"rotate_every": 5
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
241
|
```
|
|
241
242
|
|
|
242
243
|
Then just use /model and tab to select your round-robin model!
|
|
243
244
|
|
|
245
|
+
The `rotate_every` parameter controls how many requests are made to each model before rotating to the next one. In this example, the round-robin model will use each Qwen model for 5 consecutive requests before moving to the next model in the sequence.
|
|
246
|
+
|
|
244
247
|
### Benefits
|
|
245
248
|
- **Rate Limit Protection**: Automatically distribute requests across multiple models
|
|
246
249
|
- **Load Balancing**: Share workload between different model providers
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
code_puppy/__init__.py,sha256=ehbM1-wMjNmOXk_DBhhJECFyBv2dRHwwo7ucjHeM68E,107
|
|
2
2
|
code_puppy/__main__.py,sha256=pDVssJOWP8A83iFkxMLY9YteHYat0EyWDQqMkKHpWp4,203
|
|
3
|
-
code_puppy/agent.py,sha256=
|
|
3
|
+
code_puppy/agent.py,sha256=3pbcyM_WjY4OsOYtWxfglpcnD7H8TxUJLNFELVMgJcA,7000
|
|
4
4
|
code_puppy/callbacks.py,sha256=6wYB6K_fGSCkKKEFaYOYkJT45WaV5W_NhUIzcvVH_nU,5060
|
|
5
|
-
code_puppy/config.py,sha256=
|
|
5
|
+
code_puppy/config.py,sha256=n4Em_txe-mz5UVTyCO2OQe4JzX2yUyVG7WT3NdvOVbU,15800
|
|
6
6
|
code_puppy/http_utils.py,sha256=BAvt4hed7fVMXglA7eS9gOb08h2YTuOyai6VmQq09fg,3432
|
|
7
7
|
code_puppy/main.py,sha256=Vv5HSJnkgZhCvvOoXrJ2zqM5P-i47-RcYAU00Z1Pfx0,21733
|
|
8
8
|
code_puppy/message_history_processor.py,sha256=O2rKp7W6YeIg93W8b0XySTUEQgIZm0f_06--_kzHugM,16145
|
|
9
|
-
code_puppy/model_factory.py,sha256
|
|
9
|
+
code_puppy/model_factory.py,sha256=-_0kJ7qYmRTDk0v3mfp-UrYf0IaDLyG8IMBweDECwJg,11917
|
|
10
10
|
code_puppy/models.json,sha256=dAfpMMI2EEeOMv0ynHSmMuJAYDLcZrs5gCLX3voC4-A,3252
|
|
11
11
|
code_puppy/reopenable_async_client.py,sha256=4UJRaMp5np8cbef9F0zKQ7TPKOfyf5U-Kv-0zYUWDho,8274
|
|
12
|
-
code_puppy/round_robin_model.py,sha256=
|
|
12
|
+
code_puppy/round_robin_model.py,sha256=VWGCbK0-0rLpnrdxlmND5JsKXiNZZWFMIjF4_OL3STE,5594
|
|
13
13
|
code_puppy/state_management.py,sha256=o4mNBCPblRyVrNBH-992-1YqffgH6AKHU7iZRqgP1LI,5925
|
|
14
14
|
code_puppy/status_display.py,sha256=F6eEAkGePDp4StM2BWj-uLLQTDGtJrf0IufzCeP1rRg,8336
|
|
15
15
|
code_puppy/summarization_agent.py,sha256=-e6yUGZ22ahSaF0y7QhgVcQBfx5ktNUkPxBIWQfPaA4,3275
|
|
@@ -27,7 +27,7 @@ code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZ
|
|
|
27
27
|
code_puppy/command_line/command_handler.py,sha256=1o9tKAGycpHFDBldYRAAvY5HJ6QAfikLPrXTEkfw37o,21137
|
|
28
28
|
code_puppy/command_line/file_path_completion.py,sha256=gw8NpIxa6GOpczUJRyh7VNZwoXKKn-yvCqit7h2y6Gg,2931
|
|
29
29
|
code_puppy/command_line/load_context_completion.py,sha256=6eZxV6Bs-EFwZjN93V8ZDZUC-6RaWxvtZk-04Wtikyw,2240
|
|
30
|
-
code_puppy/command_line/meta_command_handler.py,sha256=
|
|
30
|
+
code_puppy/command_line/meta_command_handler.py,sha256=xWa3_V1xQPi25V86eaTXa3NXPT3ygiKACb50uuy6TiM,5695
|
|
31
31
|
code_puppy/command_line/model_picker_completion.py,sha256=adxp3NZaDV67YqaGv0SG7WVvOTXN0UwkkLqxTsknAvs,4126
|
|
32
32
|
code_puppy/command_line/motd.py,sha256=PEdkp3ZnydVfvd7mNJylm8YyFNUKg9jmY6uwkA1em8c,2152
|
|
33
33
|
code_puppy/command_line/prompt_toolkit_completion.py,sha256=vmsA0F4TfXZ3gjVzCfSNM3TIY-w3z_fSteTCcia2zAU,9379
|
|
@@ -126,9 +126,9 @@ code_puppy/tui/tests/test_sidebar_history_navigation.py,sha256=JGiyua8A2B8dLfwiE
|
|
|
126
126
|
code_puppy/tui/tests/test_status_bar.py,sha256=nYT_FZGdmqnnbn6o0ZuOkLtNUtJzLSmtX8P72liQ5Vo,1797
|
|
127
127
|
code_puppy/tui/tests/test_timestamped_history.py,sha256=nVXt9hExZZ_8MFP-AZj4L4bB_1Eo_mc-ZhVICzTuw3I,1799
|
|
128
128
|
code_puppy/tui/tests/test_tools.py,sha256=kgzzAkK4r0DPzQwHHD4cePpVNgrHor6cFr05Pg6DBWg,2687
|
|
129
|
-
code_puppy-0.0.
|
|
130
|
-
code_puppy-0.0.
|
|
131
|
-
code_puppy-0.0.
|
|
132
|
-
code_puppy-0.0.
|
|
133
|
-
code_puppy-0.0.
|
|
134
|
-
code_puppy-0.0.
|
|
129
|
+
code_puppy-0.0.146.data/data/code_puppy/models.json,sha256=dAfpMMI2EEeOMv0ynHSmMuJAYDLcZrs5gCLX3voC4-A,3252
|
|
130
|
+
code_puppy-0.0.146.dist-info/METADATA,sha256=wciu-hCWux40BXIFeOy3xtNnZ66bebBHJYMOU9AgQHs,22019
|
|
131
|
+
code_puppy-0.0.146.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
132
|
+
code_puppy-0.0.146.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
|
|
133
|
+
code_puppy-0.0.146.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
134
|
+
code_puppy-0.0.146.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|