code-puppy 0.0.197__py3-none-any.whl → 0.0.199__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 +14 -9
- code_puppy/agents/json_agent.py +8 -0
- code_puppy/command_line/command_handler.py +45 -18
- code_puppy/command_line/model_picker_completion.py +14 -5
- code_puppy/config.py +6 -0
- code_puppy/main.py +4 -1
- code_puppy/tui/screens/settings.py +14 -0
- {code_puppy-0.0.197.dist-info → code_puppy-0.0.199.dist-info}/METADATA +1 -1
- {code_puppy-0.0.197.dist-info → code_puppy-0.0.199.dist-info}/RECORD +13 -13
- {code_puppy-0.0.197.data → code_puppy-0.0.199.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.197.dist-info → code_puppy-0.0.199.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.197.dist-info → code_puppy-0.0.199.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.197.dist-info → code_puppy-0.0.199.dist-info}/licenses/LICENSE +0 -0
code_puppy/agents/base_agent.py
CHANGED
@@ -460,16 +460,21 @@ class BaseAgent(ABC):
|
|
460
460
|
|
461
461
|
def get_model_context_length(self) -> int:
|
462
462
|
"""
|
463
|
-
|
464
|
-
"""
|
465
|
-
model_configs = ModelFactory.load_config()
|
466
|
-
model_name = get_global_model_name()
|
467
|
-
|
468
|
-
# Get context length from model config
|
469
|
-
model_config = model_configs.get(model_name, {})
|
470
|
-
context_length = model_config.get("context_length", 128000) # Default value
|
463
|
+
Return the context length for this agent's effective model.
|
471
464
|
|
472
|
-
|
465
|
+
Honors per-agent pinned model via `self.get_model_name()`; falls back
|
466
|
+
to global model when no pin is set. Defaults conservatively on failure.
|
467
|
+
"""
|
468
|
+
try:
|
469
|
+
model_configs = ModelFactory.load_config()
|
470
|
+
# Use the agent's effective model (respects /pin_model)
|
471
|
+
model_name = self.get_model_name()
|
472
|
+
model_config = model_configs.get(model_name, {})
|
473
|
+
context_length = model_config.get("context_length", 128000)
|
474
|
+
return int(context_length)
|
475
|
+
except Exception:
|
476
|
+
# Be safe; don't blow up status/compaction if model lookup fails
|
477
|
+
return 128000
|
473
478
|
|
474
479
|
def prune_interrupted_tool_calls(
|
475
480
|
self, messages: List[ModelMessage]
|
code_puppy/agents/json_agent.py
CHANGED
@@ -101,6 +101,14 @@ class JSONAgent(BaseAgent):
|
|
101
101
|
"""Get tool configuration from JSON config."""
|
102
102
|
return self._config.get("tools_config")
|
103
103
|
|
104
|
+
def refresh_config(self) -> None:
|
105
|
+
"""Reload the agent configuration from disk.
|
106
|
+
|
107
|
+
This keeps long-lived agent instances in sync after external edits.
|
108
|
+
"""
|
109
|
+
self._config = self._load_config()
|
110
|
+
self._validate_config()
|
111
|
+
|
104
112
|
def get_model_name(self) -> Optional[str]:
|
105
113
|
"""Get pinned model name from JSON config, if specified.
|
106
114
|
|
@@ -5,7 +5,11 @@ from pathlib import Path
|
|
5
5
|
from code_puppy.command_line.model_picker_completion import update_model_in_input
|
6
6
|
from code_puppy.command_line.motd import print_motd
|
7
7
|
from code_puppy.command_line.utils import make_directory_table
|
8
|
-
from code_puppy.config import
|
8
|
+
from code_puppy.config import (
|
9
|
+
CONTEXTS_DIR,
|
10
|
+
finalize_autosave_session,
|
11
|
+
get_config_keys,
|
12
|
+
)
|
9
13
|
from code_puppy.session_storage import list_sessions, load_session, save_session
|
10
14
|
from code_puppy.tools.tools_content import tools_content
|
11
15
|
|
@@ -429,31 +433,44 @@ def handle_command(command: str):
|
|
429
433
|
import uuid
|
430
434
|
|
431
435
|
group_id = str(uuid.uuid4())
|
436
|
+
available_agents = get_available_agents()
|
432
437
|
|
433
|
-
if
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
new_agent = get_current_agent()
|
438
|
-
emit_success(
|
439
|
-
f"Switched to agent: {new_agent.display_name}",
|
438
|
+
if agent_name not in available_agents:
|
439
|
+
emit_error(f"Agent '{agent_name}' not found", message_group=group_id)
|
440
|
+
emit_warning(
|
441
|
+
f"Available agents: {', '.join(available_agents.keys())}",
|
440
442
|
message_group=group_id,
|
441
443
|
)
|
442
|
-
emit_info(f"[dim]{new_agent.description}[/dim]", message_group=group_id)
|
443
444
|
return True
|
444
|
-
else:
|
445
|
-
# Generate a group ID for all messages in this command
|
446
|
-
import uuid
|
447
445
|
|
448
|
-
|
446
|
+
current_agent = get_current_agent()
|
447
|
+
if current_agent.name == agent_name:
|
448
|
+
emit_info(
|
449
|
+
f"Already using agent: {current_agent.display_name}",
|
450
|
+
message_group=group_id,
|
451
|
+
)
|
452
|
+
return True
|
449
453
|
|
450
|
-
|
451
|
-
|
454
|
+
new_session_id = finalize_autosave_session()
|
455
|
+
if not set_current_agent(agent_name):
|
452
456
|
emit_warning(
|
453
|
-
|
457
|
+
"Agent switch failed after autosave rotation. Your context was preserved.",
|
454
458
|
message_group=group_id,
|
455
459
|
)
|
456
460
|
return True
|
461
|
+
|
462
|
+
new_agent = get_current_agent()
|
463
|
+
new_agent.reload_code_generation_agent()
|
464
|
+
emit_success(
|
465
|
+
f"Switched to agent: {new_agent.display_name}",
|
466
|
+
message_group=group_id,
|
467
|
+
)
|
468
|
+
emit_info(f"[dim]{new_agent.description}[/dim]", message_group=group_id)
|
469
|
+
emit_info(
|
470
|
+
f"[dim]Auto-save session rotated to: {new_session_id}[/dim]",
|
471
|
+
message_group=group_id,
|
472
|
+
)
|
473
|
+
return True
|
457
474
|
else:
|
458
475
|
emit_warning("Usage: /agent [agent-name]")
|
459
476
|
return True
|
@@ -593,12 +610,22 @@ def handle_command(command: str):
|
|
593
610
|
|
594
611
|
emit_success(f"Model '{model_name}' pinned to agent '{agent_name}'")
|
595
612
|
|
596
|
-
# If this is the current agent,
|
613
|
+
# If this is the current agent, refresh it so the prompt updates immediately
|
597
614
|
from code_puppy.agents import get_current_agent
|
598
615
|
|
599
616
|
current_agent = get_current_agent()
|
600
617
|
if current_agent.name == agent_name:
|
601
|
-
|
618
|
+
try:
|
619
|
+
if is_json_agent and hasattr(current_agent, "refresh_config"):
|
620
|
+
current_agent.refresh_config()
|
621
|
+
current_agent.reload_code_generation_agent()
|
622
|
+
emit_info(
|
623
|
+
f"Active agent reloaded with pinned model '{model_name}'"
|
624
|
+
)
|
625
|
+
except Exception as reload_error:
|
626
|
+
emit_warning(
|
627
|
+
f"Pinned model applied but reload failed: {reload_error}"
|
628
|
+
)
|
602
629
|
|
603
630
|
return True
|
604
631
|
|
@@ -29,13 +29,22 @@ def set_active_model(model_name: str):
|
|
29
29
|
Sets the active model name by updating the config (for persistence).
|
30
30
|
"""
|
31
31
|
set_model_name(model_name)
|
32
|
-
# Reload agent
|
32
|
+
# Reload the currently active agent so the new model takes effect immediately
|
33
33
|
try:
|
34
|
-
from code_puppy.
|
35
|
-
|
36
|
-
|
34
|
+
from code_puppy.agents import get_current_agent
|
35
|
+
|
36
|
+
current_agent = get_current_agent()
|
37
|
+
# JSON agents may need to refresh their config before reload
|
38
|
+
if hasattr(current_agent, "refresh_config"):
|
39
|
+
try:
|
40
|
+
current_agent.refresh_config()
|
41
|
+
except Exception:
|
42
|
+
# Non-fatal, continue to reload
|
43
|
+
...
|
44
|
+
current_agent.reload_code_generation_agent()
|
37
45
|
except Exception:
|
38
|
-
|
46
|
+
# Swallow errors to avoid breaking the prompt flow; model persists for next run
|
47
|
+
pass
|
39
48
|
|
40
49
|
|
41
50
|
class ModelNameCompleter(Completer):
|
code_puppy/config.py
CHANGED
@@ -784,3 +784,9 @@ def auto_save_session_if_enabled() -> bool:
|
|
784
784
|
|
785
785
|
Console().print(f"[dim]❌ Failed to auto-save session: {exc}[/dim]")
|
786
786
|
return False
|
787
|
+
|
788
|
+
|
789
|
+
def finalize_autosave_session() -> str:
|
790
|
+
"""Persist the current autosave snapshot and rotate to a fresh session."""
|
791
|
+
auto_save_session_if_enabled()
|
792
|
+
return rotate_autosave_id()
|
code_puppy/main.py
CHANGED
@@ -24,6 +24,7 @@ from code_puppy.config import (
|
|
24
24
|
AUTOSAVE_DIR,
|
25
25
|
COMMAND_HISTORY_FILE,
|
26
26
|
ensure_config_exists,
|
27
|
+
finalize_autosave_session,
|
27
28
|
initialize_command_history_file,
|
28
29
|
save_command_to_history,
|
29
30
|
)
|
@@ -414,12 +415,14 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
|
|
414
415
|
|
415
416
|
# Check for clear command (supports both `clear` and `/clear`)
|
416
417
|
if task.strip().lower() in ("clear", "/clear"):
|
417
|
-
from code_puppy.messaging import emit_system_message, emit_warning
|
418
|
+
from code_puppy.messaging import emit_info, emit_system_message, emit_warning
|
418
419
|
|
419
420
|
agent = get_current_agent()
|
421
|
+
new_session_id = finalize_autosave_session()
|
420
422
|
agent.clear_message_history()
|
421
423
|
emit_warning("Conversation history cleared!")
|
422
424
|
emit_system_message("The agent will not remember previous interactions.\n")
|
425
|
+
emit_info(f"[dim]Auto-save session rotated to: {new_session_id}[/dim]")
|
423
426
|
continue
|
424
427
|
|
425
428
|
# Handle / commands before anything else
|
@@ -217,6 +217,20 @@ class SettingsScreen(ModalScreen):
|
|
217
217
|
# Save model selection
|
218
218
|
if selected_model:
|
219
219
|
set_model_name(selected_model)
|
220
|
+
# Reload the active agent so model switch takes effect immediately
|
221
|
+
try:
|
222
|
+
from code_puppy.agents import get_current_agent
|
223
|
+
|
224
|
+
current_agent = get_current_agent()
|
225
|
+
if hasattr(current_agent, "refresh_config"):
|
226
|
+
try:
|
227
|
+
current_agent.refresh_config()
|
228
|
+
except Exception:
|
229
|
+
...
|
230
|
+
current_agent.reload_code_generation_agent()
|
231
|
+
except Exception:
|
232
|
+
# Non-fatal: settings saved; reload will happen on next run if needed
|
233
|
+
pass
|
220
234
|
|
221
235
|
set_config_value("yolo_mode", yolo_mode)
|
222
236
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
code_puppy/__init__.py,sha256=ehbM1-wMjNmOXk_DBhhJECFyBv2dRHwwo7ucjHeM68E,107
|
2
2
|
code_puppy/__main__.py,sha256=pDVssJOWP8A83iFkxMLY9YteHYat0EyWDQqMkKHpWp4,203
|
3
3
|
code_puppy/callbacks.py,sha256=ukSgVFaEO68o6J09qFwDrnmNanrVv3toTLQhS504Meo,6162
|
4
|
-
code_puppy/config.py,sha256=
|
4
|
+
code_puppy/config.py,sha256=xT-nU1U4n7u8pyzJPG18-cJZBKv5OZI2CtHLt9DGRzU,26065
|
5
5
|
code_puppy/http_utils.py,sha256=YLd8Y16idbI32JGeBXG8n5rT4o4X_zxk9FgUvK9XFo8,8248
|
6
|
-
code_puppy/main.py,sha256=
|
6
|
+
code_puppy/main.py,sha256=TIFaySHV3um9Q3BDUjCjh6s-WWqcNnTY3EsD2WdW6MQ,22245
|
7
7
|
code_puppy/model_factory.py,sha256=ZbIAJWMNKNdTCEMQK8Ig6TDDZlVNyGO9hOLHoLLPMYw,15397
|
8
8
|
code_puppy/models.json,sha256=dClUciCo2RlVDs0ZAQCIur8MOavZUEAXHEecn0uPa-4,1629
|
9
9
|
code_puppy/reopenable_async_client.py,sha256=4UJRaMp5np8cbef9F0zKQ7TPKOfyf5U-Kv-0zYUWDho,8274
|
@@ -27,13 +27,13 @@ code_puppy/agents/agent_qa_expert.py,sha256=wCGXzuAVElT5c-QigQVb8JX9Gw0JmViCUQQn
|
|
27
27
|
code_puppy/agents/agent_qa_kitten.py,sha256=5PeFFSwCFlTUvP6h5bGntx0xv5NmRwBiw0HnMqY8nLI,9107
|
28
28
|
code_puppy/agents/agent_security_auditor.py,sha256=ADafi2x4gqXw6m-Nch5vjiKjO0Urcbj0x4zxHti3gDw,3712
|
29
29
|
code_puppy/agents/agent_typescript_reviewer.py,sha256=EDY1mFkVpuJ1BPXsJFu2wQ2pfAV-90ipc_8w9ymrKPg,4054
|
30
|
-
code_puppy/agents/base_agent.py,sha256=
|
31
|
-
code_puppy/agents/json_agent.py,sha256=
|
30
|
+
code_puppy/agents/base_agent.py,sha256=EHAIQrfsM7x1lz9YHXxlidWhw35HTN4f1JIvdx469ZQ,39390
|
31
|
+
code_puppy/agents/json_agent.py,sha256=lhopDJDoiSGHvD8A6t50hi9ZBoNRKgUywfxd0Po_Dzc,4886
|
32
32
|
code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
|
33
|
-
code_puppy/command_line/command_handler.py,sha256=
|
33
|
+
code_puppy/command_line/command_handler.py,sha256=alxMe5v_4jq8Sm6HETsgfF-VoDtgExj9dVzxP77fwmY,31614
|
34
34
|
code_puppy/command_line/file_path_completion.py,sha256=gw8NpIxa6GOpczUJRyh7VNZwoXKKn-yvCqit7h2y6Gg,2931
|
35
35
|
code_puppy/command_line/load_context_completion.py,sha256=6eZxV6Bs-EFwZjN93V8ZDZUC-6RaWxvtZk-04Wtikyw,2240
|
36
|
-
code_puppy/command_line/model_picker_completion.py,sha256=
|
36
|
+
code_puppy/command_line/model_picker_completion.py,sha256=uqwpbMYnCcWUZZ10Y4pMBKBfW52wQ-KdML2PO4Xjwr0,4501
|
37
37
|
code_puppy/command_line/motd.py,sha256=PEdkp3ZnydVfvd7mNJylm8YyFNUKg9jmY6uwkA1em8c,2152
|
38
38
|
code_puppy/command_line/prompt_toolkit_completion.py,sha256=_8SUUCKfjOxgNMkcHTeB08NIjCeqL3utHljROXLTEZE,10656
|
39
39
|
code_puppy/command_line/utils.py,sha256=7eyxDHjPjPB9wGDJQQcXV_zOsGdYsFgI0SGCetVmTqE,1251
|
@@ -120,11 +120,11 @@ code_puppy/tui/screens/__init__.py,sha256=qxiJKyO3MKCNdPjUuHA2-Pnpda0JN20n7e9sU2
|
|
120
120
|
code_puppy/tui/screens/autosave_picker.py,sha256=9bazha2C5N3Xg_VcmpcTv-CYOBq_mwcECBfrQM9tHxA,5416
|
121
121
|
code_puppy/tui/screens/help.py,sha256=eJuPaOOCp7ZSUlecearqsuX6caxWv7NQszUh0tZJjBM,3232
|
122
122
|
code_puppy/tui/screens/mcp_install_wizard.py,sha256=vObpQwLbXjQsxmSg-WCasoev1usEi0pollKnL0SHu9U,27693
|
123
|
-
code_puppy/tui/screens/settings.py,sha256=
|
123
|
+
code_puppy/tui/screens/settings.py,sha256=EoMxiguyeF0srwV1bj4_MG9rrxkNthh6TdTNsxnXLfE,11460
|
124
124
|
code_puppy/tui/screens/tools.py,sha256=3pr2Xkpa9Js6Yhf1A3_wQVRzFOui-KDB82LwrsdBtyk,1715
|
125
|
-
code_puppy-0.0.
|
126
|
-
code_puppy-0.0.
|
127
|
-
code_puppy-0.0.
|
128
|
-
code_puppy-0.0.
|
129
|
-
code_puppy-0.0.
|
130
|
-
code_puppy-0.0.
|
125
|
+
code_puppy-0.0.199.data/data/code_puppy/models.json,sha256=dClUciCo2RlVDs0ZAQCIur8MOavZUEAXHEecn0uPa-4,1629
|
126
|
+
code_puppy-0.0.199.dist-info/METADATA,sha256=IV5OoNejufscIc5UvwoIbTCR0z7Worz6m0N0QFniEuI,20759
|
127
|
+
code_puppy-0.0.199.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
128
|
+
code_puppy-0.0.199.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
|
129
|
+
code_puppy-0.0.199.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
130
|
+
code_puppy-0.0.199.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|