code-puppy 0.0.173__py3-none-any.whl → 0.0.174__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 +11 -11
- code_puppy/agents/__init__.py +4 -6
- code_puppy/agents/agent_manager.py +15 -187
- code_puppy/agents/base_agent.py +470 -63
- code_puppy/command_line/command_handler.py +40 -41
- code_puppy/command_line/mcp/start_all_command.py +3 -6
- code_puppy/command_line/mcp/start_command.py +0 -5
- code_puppy/command_line/mcp/stop_all_command.py +3 -6
- code_puppy/command_line/mcp/stop_command.py +2 -6
- code_puppy/command_line/model_picker_completion.py +2 -2
- code_puppy/command_line/prompt_toolkit_completion.py +2 -2
- code_puppy/config.py +2 -2
- code_puppy/main.py +12 -49
- code_puppy/summarization_agent.py +2 -2
- code_puppy/tools/agent_tools.py +5 -4
- code_puppy/tools/browser/vqa_agent.py +1 -3
- code_puppy/tui/app.py +48 -77
- code_puppy/tui/screens/settings.py +2 -2
- {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/METADATA +2 -2
- {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/RECORD +24 -29
- code_puppy/agents/agent_orchestrator.json +0 -26
- code_puppy/agents/runtime_manager.py +0 -272
- code_puppy/command_line/meta_command_handler.py +0 -153
- code_puppy/message_history_processor.py +0 -408
- code_puppy/state_management.py +0 -58
- {code_puppy-0.0.173.data → code_puppy-0.0.174.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/licenses/LICENSE +0 -0
code_puppy/agent.py
CHANGED
@@ -125,22 +125,22 @@ def reload_code_generation_agent(message_group: str | None):
|
|
125
125
|
message_group = str(uuid.uuid4())
|
126
126
|
global _code_generation_agent, _LAST_MODEL_NAME
|
127
127
|
from code_puppy.agents import clear_agent_cache
|
128
|
-
from code_puppy.config import clear_model_cache,
|
128
|
+
from code_puppy.config import clear_model_cache, get_global_model_name
|
129
129
|
|
130
130
|
# Clear both ModelFactory cache and config cache when force reloading
|
131
131
|
clear_model_cache()
|
132
132
|
clear_agent_cache()
|
133
133
|
|
134
134
|
# Check if current agent has a pinned model
|
135
|
-
from code_puppy.agents import
|
135
|
+
from code_puppy.agents import get_current_agent
|
136
136
|
|
137
|
-
agent_config =
|
137
|
+
agent_config = get_current_agent()
|
138
138
|
agent_model_name = None
|
139
139
|
if hasattr(agent_config, "get_model_name"):
|
140
140
|
agent_model_name = agent_config.get_model_name()
|
141
141
|
|
142
142
|
# Use agent-specific model if pinned, otherwise use global model
|
143
|
-
model_name = agent_model_name if agent_model_name else
|
143
|
+
model_name = agent_model_name if agent_model_name else get_global_model_name()
|
144
144
|
emit_info(
|
145
145
|
f"[bold cyan]Loading Model: {model_name}[/bold cyan]",
|
146
146
|
message_group=message_group,
|
@@ -149,7 +149,7 @@ def reload_code_generation_agent(message_group: str | None):
|
|
149
149
|
model = ModelFactory.get_model(model_name, models_config)
|
150
150
|
|
151
151
|
# Get agent-specific system prompt
|
152
|
-
agent_config =
|
152
|
+
agent_config = get_current_agent()
|
153
153
|
emit_info(
|
154
154
|
f"[bold magenta]Loading Agent: {agent_config.display_name}[/bold magenta]",
|
155
155
|
message_group=message_group,
|
@@ -165,8 +165,8 @@ def reload_code_generation_agent(message_group: str | None):
|
|
165
165
|
# Configure model settings with max_tokens if set
|
166
166
|
model_settings_dict = {"seed": 42}
|
167
167
|
# Get current agent to use its method
|
168
|
-
from code_puppy.agents import
|
169
|
-
current_agent =
|
168
|
+
from code_puppy.agents import get_current_agent
|
169
|
+
current_agent = get_current_agent()
|
170
170
|
output_tokens = max(2048, min(int(0.05 * current_agent.get_model_context_length()) - 1024, 16384))
|
171
171
|
console.print(f"Max output tokens per message: {output_tokens}")
|
172
172
|
model_settings_dict["max_tokens"] = output_tokens
|
@@ -207,15 +207,15 @@ def get_code_generation_agent(force_reload=False, message_group: str | None = No
|
|
207
207
|
global _code_generation_agent, _LAST_MODEL_NAME
|
208
208
|
if message_group is None:
|
209
209
|
message_group = str(uuid.uuid4())
|
210
|
-
from code_puppy.config import
|
210
|
+
from code_puppy.config import get_global_model_name
|
211
211
|
|
212
212
|
# Get the global model name
|
213
|
-
global_model_name =
|
213
|
+
global_model_name = get_global_model_name()
|
214
214
|
|
215
215
|
# Check if current agent has a pinned model
|
216
|
-
from code_puppy.agents import
|
216
|
+
from code_puppy.agents import get_current_agent
|
217
217
|
|
218
|
-
agent_config =
|
218
|
+
agent_config = get_current_agent()
|
219
219
|
agent_model_name = None
|
220
220
|
if hasattr(agent_config, "get_model_name"):
|
221
221
|
agent_model_name = agent_config.get_model_name()
|
code_puppy/agents/__init__.py
CHANGED
@@ -6,20 +6,18 @@ configurations, each with their own system prompts and tool sets.
|
|
6
6
|
|
7
7
|
from .agent_manager import (
|
8
8
|
get_available_agents,
|
9
|
-
|
9
|
+
get_current_agent,
|
10
10
|
set_current_agent,
|
11
|
-
|
11
|
+
load_agent,
|
12
12
|
get_agent_descriptions,
|
13
|
-
clear_agent_cache,
|
14
13
|
refresh_agents,
|
15
14
|
)
|
16
15
|
|
17
16
|
__all__ = [
|
18
17
|
"get_available_agents",
|
19
|
-
"
|
18
|
+
"get_current_agent",
|
20
19
|
"set_current_agent",
|
21
|
-
"
|
20
|
+
"load_agent",
|
22
21
|
"get_agent_descriptions",
|
23
|
-
"clear_agent_cache",
|
24
22
|
"refresh_agents",
|
25
23
|
]
|
@@ -8,14 +8,14 @@ import uuid
|
|
8
8
|
from pathlib import Path
|
9
9
|
from typing import Dict, Optional, Type, Union
|
10
10
|
|
11
|
-
from
|
12
|
-
from
|
13
|
-
from .base_agent import BaseAgent
|
14
|
-
from .json_agent import JSONAgent, discover_json_agents
|
11
|
+
from code_puppy.callbacks import on_agent_reload
|
12
|
+
from code_puppy.messaging import emit_warning
|
13
|
+
from code_puppy.agents.base_agent import BaseAgent
|
14
|
+
from code_puppy.agents.json_agent import JSONAgent, discover_json_agents
|
15
15
|
|
16
16
|
# Registry of available agents (Python classes and JSON file paths)
|
17
17
|
_AGENT_REGISTRY: Dict[str, Union[Type[BaseAgent], str]] = {}
|
18
|
-
|
18
|
+
_CURRENT_AGENT: Optional[BaseAgent] = None
|
19
19
|
|
20
20
|
# Terminal session-based agent selection
|
21
21
|
_SESSION_AGENTS_CACHE: dict[str, str] = {}
|
@@ -146,40 +146,6 @@ def _ensure_session_cache_loaded() -> None:
|
|
146
146
|
_SESSION_FILE_LOADED = True
|
147
147
|
|
148
148
|
|
149
|
-
# Persistent storage for agent message histories
|
150
|
-
_AGENT_HISTORIES: Dict[str, Dict[str, any]] = {}
|
151
|
-
# Structure: {agent_name: {"message_history": [...], "compacted_hashes": set(...)}}
|
152
|
-
|
153
|
-
|
154
|
-
def _save_agent_history(agent_name: str, agent: BaseAgent) -> None:
|
155
|
-
"""Save an agent's message history to persistent storage.
|
156
|
-
|
157
|
-
Args:
|
158
|
-
agent_name: The name of the agent
|
159
|
-
agent: The agent instance to save history from
|
160
|
-
"""
|
161
|
-
global _AGENT_HISTORIES
|
162
|
-
_AGENT_HISTORIES[agent_name] = {
|
163
|
-
"message_history": agent.get_message_history().copy(),
|
164
|
-
"compacted_hashes": agent.get_compacted_message_hashes().copy(),
|
165
|
-
}
|
166
|
-
|
167
|
-
|
168
|
-
def _restore_agent_history(agent_name: str, agent: BaseAgent) -> None:
|
169
|
-
"""Restore an agent's message history from persistent storage.
|
170
|
-
|
171
|
-
Args:
|
172
|
-
agent_name: The name of the agent
|
173
|
-
agent: The agent instance to restore history to
|
174
|
-
"""
|
175
|
-
global _AGENT_HISTORIES
|
176
|
-
if agent_name in _AGENT_HISTORIES:
|
177
|
-
stored_data = _AGENT_HISTORIES[agent_name]
|
178
|
-
agent.set_message_history(stored_data["message_history"])
|
179
|
-
# Restore compacted hashes
|
180
|
-
for hash_val in stored_data["compacted_hashes"]:
|
181
|
-
agent.add_compacted_message_hash(hash_val)
|
182
|
-
|
183
149
|
|
184
150
|
def _discover_agents(message_group_id: Optional[str] = None):
|
185
151
|
"""Dynamically discover all agent classes and JSON agents."""
|
@@ -281,21 +247,17 @@ def set_current_agent(agent_name: str) -> bool:
|
|
281
247
|
Returns:
|
282
248
|
True if the agent was set successfully, False if agent not found.
|
283
249
|
"""
|
250
|
+
global _CURRENT_AGENT
|
251
|
+
|
284
252
|
# Generate a message group ID for agent switching
|
285
253
|
message_group_id = str(uuid.uuid4())
|
286
254
|
_discover_agents(message_group_id=message_group_id)
|
287
255
|
|
288
256
|
# Save current agent's history before switching
|
289
|
-
global _CURRENT_AGENT_CONFIG, _CURRENT_AGENT_NAME
|
290
|
-
if _CURRENT_AGENT_CONFIG is not None:
|
291
|
-
_save_agent_history(_CURRENT_AGENT_CONFIG.name, _CURRENT_AGENT_CONFIG)
|
292
257
|
|
293
258
|
# Clear the cached config when switching agents
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
# Restore the agent's history if it exists
|
298
|
-
_restore_agent_history(agent_name, agent_obj)
|
259
|
+
agent_obj = load_agent(agent_name)
|
260
|
+
_CURRENT_AGENT = agent_obj
|
299
261
|
|
300
262
|
# Update session-based agent selection and persist to disk
|
301
263
|
_ensure_session_cache_loaded()
|
@@ -307,24 +269,22 @@ def set_current_agent(agent_name: str) -> bool:
|
|
307
269
|
return True
|
308
270
|
|
309
271
|
|
310
|
-
def
|
272
|
+
def get_current_agent() -> BaseAgent:
|
311
273
|
"""Get the current agent configuration.
|
312
274
|
|
313
275
|
Returns:
|
314
276
|
The current agent configuration instance.
|
315
277
|
"""
|
316
|
-
global
|
278
|
+
global _CURRENT_AGENT
|
317
279
|
|
318
|
-
if
|
280
|
+
if _CURRENT_AGENT is None:
|
319
281
|
agent_name = get_current_agent_name()
|
320
|
-
|
321
|
-
# Restore the agent's history if it exists
|
322
|
-
_restore_agent_history(agent_name, _CURRENT_AGENT_CONFIG)
|
282
|
+
_CURRENT_AGENT = load_agent(agent_name)
|
323
283
|
|
324
|
-
return
|
284
|
+
return _CURRENT_AGENT
|
325
285
|
|
326
286
|
|
327
|
-
def
|
287
|
+
def load_agent(agent_name: str) -> BaseAgent:
|
328
288
|
"""Load an agent configuration by name.
|
329
289
|
|
330
290
|
Args:
|
@@ -380,26 +340,6 @@ def get_agent_descriptions() -> Dict[str, str]:
|
|
380
340
|
return descriptions
|
381
341
|
|
382
342
|
|
383
|
-
def clear_agent_cache():
|
384
|
-
"""Clear the cached agent configuration to force reload."""
|
385
|
-
global _CURRENT_AGENT_CONFIG
|
386
|
-
_CURRENT_AGENT_CONFIG = None
|
387
|
-
|
388
|
-
|
389
|
-
def reset_to_default_agent():
|
390
|
-
"""Reset the current agent to the default (code-puppy) for this terminal session.
|
391
|
-
|
392
|
-
This is useful for testing or when you want to start fresh.
|
393
|
-
"""
|
394
|
-
global _CURRENT_AGENT_CONFIG
|
395
|
-
_ensure_session_cache_loaded()
|
396
|
-
session_id = get_terminal_session_id()
|
397
|
-
if session_id in _SESSION_AGENTS_CACHE:
|
398
|
-
del _SESSION_AGENTS_CACHE[session_id]
|
399
|
-
_save_session_data(_SESSION_AGENTS_CACHE)
|
400
|
-
_CURRENT_AGENT_CONFIG = None
|
401
|
-
|
402
|
-
|
403
343
|
def refresh_agents():
|
404
344
|
"""Refresh the agent discovery to pick up newly created agents.
|
405
345
|
|
@@ -408,115 +348,3 @@ def refresh_agents():
|
|
408
348
|
# Generate a message group ID for agent refreshing
|
409
349
|
message_group_id = str(uuid.uuid4())
|
410
350
|
_discover_agents(message_group_id=message_group_id)
|
411
|
-
|
412
|
-
|
413
|
-
def clear_all_agent_histories():
|
414
|
-
"""Clear all agent message histories from persistent storage.
|
415
|
-
|
416
|
-
This is useful for debugging or when you want a fresh start.
|
417
|
-
"""
|
418
|
-
global _AGENT_HISTORIES
|
419
|
-
_AGENT_HISTORIES.clear()
|
420
|
-
# Also clear the current agent's history
|
421
|
-
if _CURRENT_AGENT_CONFIG is not None:
|
422
|
-
_CURRENT_AGENT_CONFIG.messages = []
|
423
|
-
|
424
|
-
|
425
|
-
def cleanup_dead_terminal_sessions() -> int:
|
426
|
-
"""Clean up terminal sessions for processes that no longer exist.
|
427
|
-
|
428
|
-
Returns:
|
429
|
-
int: Number of dead sessions removed
|
430
|
-
"""
|
431
|
-
_ensure_session_cache_loaded()
|
432
|
-
original_count = len(_SESSION_AGENTS_CACHE)
|
433
|
-
cleaned_cache = _cleanup_dead_sessions(_SESSION_AGENTS_CACHE)
|
434
|
-
|
435
|
-
if len(cleaned_cache) != original_count:
|
436
|
-
_SESSION_AGENTS_CACHE.clear()
|
437
|
-
_SESSION_AGENTS_CACHE.update(cleaned_cache)
|
438
|
-
_save_session_data(_SESSION_AGENTS_CACHE)
|
439
|
-
|
440
|
-
return original_count - len(cleaned_cache)
|
441
|
-
|
442
|
-
|
443
|
-
# Agent-aware message history functions
|
444
|
-
def get_current_agent_message_history():
|
445
|
-
"""Get the message history for the currently active agent.
|
446
|
-
|
447
|
-
Returns:
|
448
|
-
List of messages from the current agent's conversation history.
|
449
|
-
"""
|
450
|
-
current_agent = get_current_agent_config()
|
451
|
-
return current_agent.get_message_history()
|
452
|
-
|
453
|
-
|
454
|
-
def set_current_agent_message_history(history):
|
455
|
-
"""Set the message history for the currently active agent.
|
456
|
-
|
457
|
-
Args:
|
458
|
-
history: List of messages to set as the current agent's conversation history.
|
459
|
-
"""
|
460
|
-
current_agent = get_current_agent_config()
|
461
|
-
current_agent.set_message_history(history)
|
462
|
-
# Also update persistent storage
|
463
|
-
_save_agent_history(current_agent.name, current_agent)
|
464
|
-
|
465
|
-
|
466
|
-
def clear_current_agent_message_history():
|
467
|
-
"""Clear the message history for the currently active agent."""
|
468
|
-
current_agent = get_current_agent_config()
|
469
|
-
current_agent.clear_message_history()
|
470
|
-
# Also clear from persistent storage
|
471
|
-
global _AGENT_HISTORIES
|
472
|
-
if current_agent.name in _AGENT_HISTORIES:
|
473
|
-
_AGENT_HISTORIES[current_agent.name] = {
|
474
|
-
"message_history": [],
|
475
|
-
"compacted_hashes": set(),
|
476
|
-
}
|
477
|
-
|
478
|
-
|
479
|
-
def append_to_current_agent_message_history(message):
|
480
|
-
"""Append a message to the currently active agent's history.
|
481
|
-
|
482
|
-
Args:
|
483
|
-
message: Message to append to the current agent's conversation history.
|
484
|
-
"""
|
485
|
-
current_agent = get_current_agent_config()
|
486
|
-
current_agent.append_to_message_history(message)
|
487
|
-
# Also update persistent storage
|
488
|
-
_save_agent_history(current_agent.name, current_agent)
|
489
|
-
|
490
|
-
|
491
|
-
def extend_current_agent_message_history(history):
|
492
|
-
"""Extend the currently active agent's message history with multiple messages.
|
493
|
-
|
494
|
-
Args:
|
495
|
-
history: List of messages to append to the current agent's conversation history.
|
496
|
-
"""
|
497
|
-
current_agent = get_current_agent_config()
|
498
|
-
current_agent.extend_message_history(history)
|
499
|
-
# Also update persistent storage
|
500
|
-
_save_agent_history(current_agent.name, current_agent)
|
501
|
-
|
502
|
-
|
503
|
-
def get_current_agent_compacted_message_hashes():
|
504
|
-
"""Get the set of compacted message hashes for the currently active agent.
|
505
|
-
|
506
|
-
Returns:
|
507
|
-
Set of hashes for messages that have been compacted/summarized.
|
508
|
-
"""
|
509
|
-
current_agent = get_current_agent_config()
|
510
|
-
return current_agent.get_compacted_message_hashes()
|
511
|
-
|
512
|
-
|
513
|
-
def add_current_agent_compacted_message_hash(message_hash: str):
|
514
|
-
"""Add a message hash to the current agent's set of compacted message hashes.
|
515
|
-
|
516
|
-
Args:
|
517
|
-
message_hash: Hash of a message that has been compacted/summarized.
|
518
|
-
"""
|
519
|
-
current_agent = get_current_agent_config()
|
520
|
-
current_agent.add_compacted_message_hash(message_hash)
|
521
|
-
# Also update persistent storage
|
522
|
-
_save_agent_history(current_agent.name, current_agent)
|