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/tui/app.py
CHANGED
|
@@ -12,27 +12,19 @@ from textual.events import Resize
|
|
|
12
12
|
from textual.reactive import reactive
|
|
13
13
|
from textual.widgets import Footer, ListView
|
|
14
14
|
|
|
15
|
-
from code_puppy.agent import get_code_generation_agent, get_custom_usage_limits
|
|
16
|
-
from code_puppy.agents.runtime_manager import get_runtime_agent_manager
|
|
17
15
|
from code_puppy.command_line.command_handler import handle_command
|
|
18
16
|
from code_puppy.config import (
|
|
19
|
-
|
|
17
|
+
get_global_model_name,
|
|
20
18
|
get_puppy_name,
|
|
21
19
|
initialize_command_history_file,
|
|
22
20
|
save_command_to_history,
|
|
23
21
|
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
prune_interrupted_tool_calls,
|
|
27
|
-
)
|
|
22
|
+
# message_history_accumulator and prune_interrupted_tool_calls have been moved to BaseAgent class
|
|
23
|
+
from code_puppy.agents.agent_manager import get_current_agent
|
|
28
24
|
|
|
29
25
|
# Import our message queue system
|
|
30
26
|
from code_puppy.messaging import TUIRenderer, get_global_queue
|
|
31
|
-
|
|
32
|
-
clear_message_history,
|
|
33
|
-
get_message_history,
|
|
34
|
-
set_message_history,
|
|
35
|
-
)
|
|
27
|
+
|
|
36
28
|
from code_puppy.tui.components import (
|
|
37
29
|
ChatView,
|
|
38
30
|
CustomTextArea,
|
|
@@ -41,7 +33,6 @@ from code_puppy.tui.components import (
|
|
|
41
33
|
StatusBar,
|
|
42
34
|
)
|
|
43
35
|
|
|
44
|
-
from .. import state_management
|
|
45
36
|
|
|
46
37
|
# Import shared message classes
|
|
47
38
|
from .messages import CommandSelected, HistoryEntrySelected
|
|
@@ -112,9 +103,9 @@ class CodePuppyTUI(App):
|
|
|
112
103
|
def _on_agent_reload(self, agent_id: str, agent_name: str) -> None:
|
|
113
104
|
"""Callback for when agent is reloaded/changed."""
|
|
114
105
|
# Get the updated agent configuration
|
|
115
|
-
from code_puppy.agents.agent_manager import
|
|
106
|
+
from code_puppy.agents.agent_manager import get_current_agent
|
|
116
107
|
|
|
117
|
-
current_agent_config =
|
|
108
|
+
current_agent_config = get_current_agent()
|
|
118
109
|
new_agent_display = (
|
|
119
110
|
current_agent_config.display_name if current_agent_config else "code-puppy"
|
|
120
111
|
)
|
|
@@ -127,7 +118,6 @@ class CodePuppyTUI(App):
|
|
|
127
118
|
|
|
128
119
|
def __init__(self, initial_command: str = None, **kwargs):
|
|
129
120
|
super().__init__(**kwargs)
|
|
130
|
-
self.agent_manager = None
|
|
131
121
|
self._current_worker = None
|
|
132
122
|
self.initial_command = initial_command
|
|
133
123
|
|
|
@@ -159,13 +149,13 @@ class CodePuppyTUI(App):
|
|
|
159
149
|
register_callback("agent_reload", self._on_agent_reload)
|
|
160
150
|
|
|
161
151
|
# Load configuration
|
|
162
|
-
self.current_model =
|
|
152
|
+
self.current_model = get_global_model_name()
|
|
163
153
|
self.puppy_name = get_puppy_name()
|
|
164
154
|
|
|
165
155
|
# Get current agent information
|
|
166
|
-
from code_puppy.agents.agent_manager import
|
|
156
|
+
from code_puppy.agents.agent_manager import get_current_agent
|
|
167
157
|
|
|
168
|
-
current_agent_config =
|
|
158
|
+
current_agent_config = get_current_agent()
|
|
169
159
|
self.current_agent = (
|
|
170
160
|
current_agent_config.display_name if current_agent_config else "code-puppy"
|
|
171
161
|
)
|
|
@@ -174,8 +164,6 @@ class CodePuppyTUI(App):
|
|
|
174
164
|
self._update_title()
|
|
175
165
|
|
|
176
166
|
# Use runtime manager to ensure we always have the current agent
|
|
177
|
-
self.agent_manager = get_runtime_agent_manager()
|
|
178
|
-
|
|
179
167
|
# Update status bar
|
|
180
168
|
status_bar = self.query_one(StatusBar)
|
|
181
169
|
status_bar.current_model = self.current_model
|
|
@@ -188,7 +176,7 @@ class CodePuppyTUI(App):
|
|
|
188
176
|
)
|
|
189
177
|
|
|
190
178
|
# Get current agent and display info
|
|
191
|
-
|
|
179
|
+
agent = get_current_agent()
|
|
192
180
|
self.add_system_message(
|
|
193
181
|
f"🐕 Loaded agent '{self.puppy_name}' with model '{self.current_model}'"
|
|
194
182
|
)
|
|
@@ -430,11 +418,6 @@ class CodePuppyTUI(App):
|
|
|
430
418
|
else:
|
|
431
419
|
# Only cancel the agent task if NO processes were killed
|
|
432
420
|
self._current_worker.cancel()
|
|
433
|
-
state_management.set_message_history(
|
|
434
|
-
prune_interrupted_tool_calls(
|
|
435
|
-
state_management.get_message_history()
|
|
436
|
-
)
|
|
437
|
-
)
|
|
438
421
|
self.add_system_message("⚠️ Processing cancelled by user")
|
|
439
422
|
# Stop spinner and clear state only when agent is actually cancelled
|
|
440
423
|
self._current_worker = None
|
|
@@ -491,55 +474,44 @@ class CodePuppyTUI(App):
|
|
|
491
474
|
return
|
|
492
475
|
|
|
493
476
|
# Process with agent
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
self.update_agent_progress("Processing", 25)
|
|
497
|
-
|
|
498
|
-
# Use agent_manager's run_with_mcp to handle MCP servers properly
|
|
499
|
-
try:
|
|
500
|
-
self.update_agent_progress("Processing", 50)
|
|
501
|
-
result = await self.agent_manager.run_with_mcp(
|
|
502
|
-
message,
|
|
503
|
-
message_history=get_message_history(),
|
|
504
|
-
usage_limits=get_custom_usage_limits(),
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
if not result or not hasattr(result, "output"):
|
|
508
|
-
self.add_error_message("Invalid response format from agent")
|
|
509
|
-
return
|
|
510
|
-
|
|
511
|
-
self.update_agent_progress("Processing", 75)
|
|
512
|
-
agent_response = result.output
|
|
513
|
-
self.add_agent_message(agent_response)
|
|
514
|
-
|
|
515
|
-
# Update message history
|
|
516
|
-
new_msgs = result.new_messages()
|
|
517
|
-
message_history_accumulator(new_msgs)
|
|
518
|
-
|
|
519
|
-
# Refresh history display to show new interaction
|
|
520
|
-
self.refresh_history_display()
|
|
477
|
+
try:
|
|
478
|
+
self.update_agent_progress("Processing", 25)
|
|
521
479
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
self.add_error_message(f"MCP/Agent error: {str(e)}")
|
|
529
|
-
else:
|
|
530
|
-
# Handle regular exceptions
|
|
531
|
-
self.add_error_message(f"MCP/Agent error: {str(eg)}")
|
|
532
|
-
finally:
|
|
533
|
-
set_message_history(
|
|
534
|
-
prune_interrupted_tool_calls(get_message_history())
|
|
535
|
-
)
|
|
536
|
-
except Exception as agent_error:
|
|
537
|
-
# Handle any other errors in agent processing
|
|
538
|
-
self.add_error_message(
|
|
539
|
-
f"Agent processing failed: {str(agent_error)}"
|
|
480
|
+
# Use agent_manager's run_with_mcp to handle MCP servers properly
|
|
481
|
+
try:
|
|
482
|
+
agent = get_current_agent()
|
|
483
|
+
self.update_agent_progress("Processing", 50)
|
|
484
|
+
result = await agent.run_with_mcp(
|
|
485
|
+
message,
|
|
540
486
|
)
|
|
541
|
-
|
|
542
|
-
|
|
487
|
+
|
|
488
|
+
if not result or not hasattr(result, "output"):
|
|
489
|
+
self.add_error_message("Invalid response format from agent")
|
|
490
|
+
return
|
|
491
|
+
|
|
492
|
+
self.update_agent_progress("Processing", 75)
|
|
493
|
+
agent_response = result.output
|
|
494
|
+
self.add_agent_message(agent_response)
|
|
495
|
+
# Refresh history display to show new interaction
|
|
496
|
+
self.refresh_history_display()
|
|
497
|
+
|
|
498
|
+
except Exception as eg:
|
|
499
|
+
# Handle TaskGroup and other exceptions
|
|
500
|
+
# BaseExceptionGroup is only available in Python 3.11+
|
|
501
|
+
if hasattr(eg, "exceptions"):
|
|
502
|
+
# Handle TaskGroup exceptions specifically (Python 3.11+)
|
|
503
|
+
for e in eg.exceptions:
|
|
504
|
+
self.add_error_message(f"MCP/Agent error: {str(e)}")
|
|
505
|
+
else:
|
|
506
|
+
# Handle regular exceptions
|
|
507
|
+
self.add_error_message(f"MCP/Agent error: {str(eg)}")
|
|
508
|
+
finally:
|
|
509
|
+
pass
|
|
510
|
+
except Exception as agent_error:
|
|
511
|
+
# Handle any other errors in agent processing
|
|
512
|
+
self.add_error_message(
|
|
513
|
+
f"Agent processing failed: {str(agent_error)}"
|
|
514
|
+
)
|
|
543
515
|
|
|
544
516
|
except Exception as e:
|
|
545
517
|
self.add_error_message(f"Error processing message: {str(e)}")
|
|
@@ -553,7 +525,6 @@ class CodePuppyTUI(App):
|
|
|
553
525
|
"""Clear the chat history."""
|
|
554
526
|
chat_view = self.query_one("#chat-view", ChatView)
|
|
555
527
|
chat_view.clear_messages()
|
|
556
|
-
clear_message_history()
|
|
557
528
|
self.add_system_message("Chat history cleared")
|
|
558
529
|
|
|
559
530
|
def action_show_help(self) -> None:
|
|
@@ -652,13 +623,13 @@ class CodePuppyTUI(App):
|
|
|
652
623
|
def handle_settings_result(result):
|
|
653
624
|
if result and result.get("success"):
|
|
654
625
|
# Update reactive variables
|
|
655
|
-
from code_puppy.config import
|
|
626
|
+
from code_puppy.config import get_global_model_name, get_puppy_name
|
|
656
627
|
|
|
657
628
|
self.puppy_name = get_puppy_name()
|
|
658
629
|
|
|
659
630
|
# Handle model change if needed
|
|
660
631
|
if result.get("model_changed"):
|
|
661
|
-
new_model =
|
|
632
|
+
new_model = get_global_model_name()
|
|
662
633
|
self.current_model = new_model
|
|
663
634
|
# Reinitialize agent with new model
|
|
664
635
|
self.agent_manager.reload_agent()
|
|
@@ -125,7 +125,7 @@ class SettingsScreen(ModalScreen):
|
|
|
125
125
|
def on_mount(self) -> None:
|
|
126
126
|
"""Load current settings when the screen mounts."""
|
|
127
127
|
from code_puppy.config import (
|
|
128
|
-
|
|
128
|
+
get_global_model_name,
|
|
129
129
|
get_owner_name,
|
|
130
130
|
get_protected_token_count,
|
|
131
131
|
get_puppy_name,
|
|
@@ -155,7 +155,7 @@ class SettingsScreen(ModalScreen):
|
|
|
155
155
|
self.load_model_options(model_select)
|
|
156
156
|
|
|
157
157
|
# Set current model selection
|
|
158
|
-
current_model =
|
|
158
|
+
current_model = get_global_model_name()
|
|
159
159
|
model_select.value = current_model
|
|
160
160
|
|
|
161
161
|
# YOLO mode is always enabled in TUI mode
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.174
|
|
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
|
|
@@ -26,7 +26,7 @@ Requires-Dist: openai>=1.99.1
|
|
|
26
26
|
Requires-Dist: pathspec>=0.11.0
|
|
27
27
|
Requires-Dist: playwright>=1.40.0
|
|
28
28
|
Requires-Dist: prompt-toolkit>=3.0.38
|
|
29
|
-
Requires-Dist: pydantic-ai
|
|
29
|
+
Requires-Dist: pydantic-ai<=0.8
|
|
30
30
|
Requires-Dist: pydantic>=2.4.0
|
|
31
31
|
Requires-Dist: pyjwt>=2.8.0
|
|
32
32
|
Requires-Dist: pytest-cov>=6.1.1
|
|
@@ -1,37 +1,32 @@
|
|
|
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=CGdK-vIwRQh27c552Glc39eqhnXJh2ZeE9D2BaYkhms,8505
|
|
4
4
|
code_puppy/callbacks.py,sha256=6wYB6K_fGSCkKKEFaYOYkJT45WaV5W_NhUIzcvVH_nU,5060
|
|
5
|
-
code_puppy/config.py,sha256=
|
|
5
|
+
code_puppy/config.py,sha256=ruPGe9f3kFI9F563NQOKuNQY12kw5eXPzbm2utJ0DO8,20639
|
|
6
6
|
code_puppy/http_utils.py,sha256=jnElpVNNIK-_gcqwsBYRImDGU-tYNfsLR7Gtme5CYzs,8423
|
|
7
|
-
code_puppy/main.py,sha256=
|
|
8
|
-
code_puppy/message_history_processor.py,sha256=SnVpUCMkbtM4RX5b6ioeG-fh--ri0bh8_yHp7ZQIAPE,16005
|
|
7
|
+
code_puppy/main.py,sha256=hVPFNN8QOuct2FFH6OMGQ3E04cmEnmO88ffTbbpfuWY,20516
|
|
9
8
|
code_puppy/model_factory.py,sha256=z9vQbcGllgMwU0On8rPvzYxkygW2Uyd3NJmRzbKv-is,13759
|
|
10
9
|
code_puppy/models.json,sha256=iXmLZGflnQcu2DRh4WUlgAhoXdvoxUc7KBhB8YxawXM,3088
|
|
11
10
|
code_puppy/reopenable_async_client.py,sha256=4UJRaMp5np8cbef9F0zKQ7TPKOfyf5U-Kv-0zYUWDho,8274
|
|
12
11
|
code_puppy/round_robin_model.py,sha256=SEN3VSwTgC5wHjx2sZsHQLPWOycf4jGwzB-EydgqkdY,5643
|
|
13
|
-
code_puppy/state_management.py,sha256=OyBSfdicKN7ObZEGs6Kbyy1JC8R8n4FZBOLIBvQZTBc,1916
|
|
14
12
|
code_puppy/status_display.py,sha256=F6eEAkGePDp4StM2BWj-uLLQTDGtJrf0IufzCeP1rRg,8336
|
|
15
|
-
code_puppy/summarization_agent.py,sha256=
|
|
13
|
+
code_puppy/summarization_agent.py,sha256=LnObgtLmM6N4z2553XXQlXAOf8R1BPSNmFSfXkjpivg,3211
|
|
16
14
|
code_puppy/tui_state.py,sha256=TT76XBVapKj6fKjFzz6oxCONeN_BZwcMILxxZcxu6-Y,1171
|
|
17
15
|
code_puppy/version_checker.py,sha256=bjLDmgGPrl7XnYwX1u13O8uFlsfikV90PK6nbA9Z9QU,1150
|
|
18
|
-
code_puppy/agents/__init__.py,sha256=
|
|
16
|
+
code_puppy/agents/__init__.py,sha256=37co1Xux3E10ynvbCBkyeTZAZpjEb-ci2uUy6nzM1hA,518
|
|
19
17
|
code_puppy/agents/agent_code_puppy.py,sha256=sbuQxLzlkMbPOyLbILbXOAHecRsxbFdQt13HJ_GEqQo,7972
|
|
20
18
|
code_puppy/agents/agent_creator_agent.py,sha256=eNOlJssQdyoQm1F7d-TZWcMXpkYmZ-w9WN-NDFXCgtw,23042
|
|
21
|
-
code_puppy/agents/agent_manager.py,sha256=
|
|
22
|
-
code_puppy/agents/agent_orchestrator.json,sha256=Iqnc0p6ICoAlUTMkEsi1XXMXJi4pdxVnWZUMaih6s5o,1267
|
|
19
|
+
code_puppy/agents/agent_manager.py,sha256=BmIxguNN3qq1S7UebxqrcdB0Q4ZuwWRVRsnYUDMgfYg,11050
|
|
23
20
|
code_puppy/agents/agent_qa_kitten.py,sha256=5PeFFSwCFlTUvP6h5bGntx0xv5NmRwBiw0HnMqY8nLI,9107
|
|
24
|
-
code_puppy/agents/base_agent.py,sha256=
|
|
21
|
+
code_puppy/agents/base_agent.py,sha256=LRBj-ap7-pjiXGbAUfNMt45W1KnCBZjfYPKENlmg89U,36701
|
|
25
22
|
code_puppy/agents/json_agent.py,sha256=y6AYE3Fx9LhmemcPzt46d7359MNnkGIjU83YBGNer2g,4533
|
|
26
|
-
code_puppy/agents/runtime_manager.py,sha256=fUOBpmETo3wTyLc5wWBfGKSX1HFRQWSpuwxYAOyA-_8,10059
|
|
27
23
|
code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
|
|
28
|
-
code_puppy/command_line/command_handler.py,sha256=
|
|
24
|
+
code_puppy/command_line/command_handler.py,sha256=z4p62jwdJXUJVVzTHStTOFyzv-PwjjNhu8bziIo8gns,27191
|
|
29
25
|
code_puppy/command_line/file_path_completion.py,sha256=gw8NpIxa6GOpczUJRyh7VNZwoXKKn-yvCqit7h2y6Gg,2931
|
|
30
26
|
code_puppy/command_line/load_context_completion.py,sha256=6eZxV6Bs-EFwZjN93V8ZDZUC-6RaWxvtZk-04Wtikyw,2240
|
|
31
|
-
code_puppy/command_line/
|
|
32
|
-
code_puppy/command_line/model_picker_completion.py,sha256=adxp3NZaDV67YqaGv0SG7WVvOTXN0UwkkLqxTsknAvs,4126
|
|
27
|
+
code_puppy/command_line/model_picker_completion.py,sha256=vYNCZS1QWu6fxF__hTwpc7jwH7h_48wUxrnITawc83E,4140
|
|
33
28
|
code_puppy/command_line/motd.py,sha256=PEdkp3ZnydVfvd7mNJylm8YyFNUKg9jmY6uwkA1em8c,2152
|
|
34
|
-
code_puppy/command_line/prompt_toolkit_completion.py,sha256=
|
|
29
|
+
code_puppy/command_line/prompt_toolkit_completion.py,sha256=O-wTYIGb9J_ONEBa-bWNFeQLnqC6LIFKsKQ7hjMbssM,9992
|
|
35
30
|
code_puppy/command_line/utils.py,sha256=7eyxDHjPjPB9wGDJQQcXV_zOsGdYsFgI0SGCetVmTqE,1251
|
|
36
31
|
code_puppy/command_line/mcp/__init__.py,sha256=0-OQuwjq_pLiTVJ1_NrirVwdRerghyKs_MTZkwPC7YY,315
|
|
37
32
|
code_puppy/command_line/mcp/add_command.py,sha256=lZ09RpFDIeghX1zhc2YIAqBASs5Ra52x5YAasUKvqJg,6409
|
|
@@ -44,11 +39,11 @@ code_puppy/command_line/mcp/logs_command.py,sha256=x_QsVGPpI5XY7RCZtiNFegc6R3csi
|
|
|
44
39
|
code_puppy/command_line/mcp/remove_command.py,sha256=MrWmXQ9jZTq1wrohFDO3ls0a1faTHCqRZocN-ynTzh8,2753
|
|
45
40
|
code_puppy/command_line/mcp/restart_command.py,sha256=-arZhayEVjTg3WErQKiBoFxbpbQcFlPXTzUI5o8AQLg,3254
|
|
46
41
|
code_puppy/command_line/mcp/search_command.py,sha256=k4CGiNJ1MKJ1_dPHd3wlwXo899nzizSUr7PsR0V9y4Y,4113
|
|
47
|
-
code_puppy/command_line/mcp/start_all_command.py,sha256=
|
|
48
|
-
code_puppy/command_line/mcp/start_command.py,sha256=
|
|
42
|
+
code_puppy/command_line/mcp/start_all_command.py,sha256=cdFi-eEAp4SKTiUvSkCAHaeq3PiujW35a3ZT7UPNlUc,4197
|
|
43
|
+
code_puppy/command_line/mcp/start_command.py,sha256=dFB64MJMHAh8v_Jq07Ux4K74P9CP239l_0BHk7wH_2A,3108
|
|
49
44
|
code_puppy/command_line/mcp/status_command.py,sha256=tQJrEDlN4DJ3n9jnKW-4kD0vL3TyUQbovb4V3nz-RsA,6640
|
|
50
|
-
code_puppy/command_line/mcp/stop_all_command.py,sha256=
|
|
51
|
-
code_puppy/command_line/mcp/stop_command.py,sha256=
|
|
45
|
+
code_puppy/command_line/mcp/stop_all_command.py,sha256=BcsvkGcSGCexCnWfpirBNxJNHP0HSGrjQP0LslHbano,3618
|
|
46
|
+
code_puppy/command_line/mcp/stop_command.py,sha256=6ruOlABIgGmuFmoakAsaqStaCUctBsA_KbvYNKmlt8U,2456
|
|
52
47
|
code_puppy/command_line/mcp/test_command.py,sha256=Pjod77DYRcA9WDZcxaCe6AUgpEXKJr42QRkxMhSjXhM,3689
|
|
53
48
|
code_puppy/command_line/mcp/utils.py,sha256=0Wt4ttYgSlVvtusYmBLKXSkjAjcsDiUxcZQAoFLUNnE,3625
|
|
54
49
|
code_puppy/command_line/mcp/wizard_utils.py,sha256=mWuE5epVgCxgGoj-VGwPO_XWVkkXjegXoIJpC9LC2TM,11075
|
|
@@ -79,7 +74,7 @@ code_puppy/messaging/spinner/spinner_base.py,sha256=474qMrTYpNfWcprFzmhaOJEOC-2r
|
|
|
79
74
|
code_puppy/messaging/spinner/textual_spinner.py,sha256=Omx9A-FSPkxYDMYgBXgYMBQnK-DMlyqLOgkFVG8cmo4,3465
|
|
80
75
|
code_puppy/plugins/__init__.py,sha256=fksDqMUiXPJ5WNuMsYsVR8ulueQRCXPlvECEyicHPtQ,1312
|
|
81
76
|
code_puppy/tools/__init__.py,sha256=BVTZ85jLHgDANwOnUSOz3UDlp8VQDq4DoGF23BRlyWw,6032
|
|
82
|
-
code_puppy/tools/agent_tools.py,sha256=
|
|
77
|
+
code_puppy/tools/agent_tools.py,sha256=h3i4c6KOxdjLr-fFjUDJdL0OR_XHo_AWx7uwfvavQJ8,5640
|
|
83
78
|
code_puppy/tools/browser_control.py,sha256=6E_Kq63cErBk-iM9-03Cq8sTWWLh-Tk2kpdrB_rMmbg,8603
|
|
84
79
|
code_puppy/tools/browser_interactions.py,sha256=m-bVsAUbdrS-P1GbS0ChO2tMMg4tMIsDX34azn_Olzs,17070
|
|
85
80
|
code_puppy/tools/browser_locators.py,sha256=ZshjhYuV600vJqXUC23oNX89AZLMvY8rlvj-9oy7GMw,19574
|
|
@@ -102,9 +97,9 @@ code_puppy/tools/browser/browser_screenshot.py,sha256=zbOMmN9_9aVDWJkC54-3zv4OEG
|
|
|
102
97
|
code_puppy/tools/browser/browser_scripts.py,sha256=BLSx1Q2F_mOOoGCoyXat3HvazTb1XaFYPXAF8CYVeX8,15071
|
|
103
98
|
code_puppy/tools/browser/browser_workflows.py,sha256=HZ0lPmEyAobPIWR-SK1E0ngW1OfULLqw8XILVT4N8Fg,5979
|
|
104
99
|
code_puppy/tools/browser/camoufox_manager.py,sha256=E1CJwQtzPFoDQiXSHHk28niWuJhk3soZ-ItxXCXWO0M,6938
|
|
105
|
-
code_puppy/tools/browser/vqa_agent.py,sha256=
|
|
100
|
+
code_puppy/tools/browser/vqa_agent.py,sha256=jUvzsk9okOZ9jskuBuij2n8wRTpTkUU2JDaHmfY8PLc,2016
|
|
106
101
|
code_puppy/tui/__init__.py,sha256=XesAxIn32zLPOmvpR2wIDxDAnnJr81a5pBJB4cZp1Xs,321
|
|
107
|
-
code_puppy/tui/app.py,sha256=
|
|
102
|
+
code_puppy/tui/app.py,sha256=gZvg7ZOUp3JurZyKZ7ehpHEhmyC0NnfmQYWF_yZm36o,38163
|
|
108
103
|
code_puppy/tui/messages.py,sha256=zQoToWI0eWdT36NEsY6RdCFzcDfAmfvoPlHv8jiCbgo,720
|
|
109
104
|
code_puppy/tui/components/__init__.py,sha256=uj5pnk3s6SEN3SbFI0ZnzaA2KK1NNg8TfUj6U-Z732U,455
|
|
110
105
|
code_puppy/tui/components/chat_view.py,sha256=NfyNXuN2idPht1rKJB4YhHVXb1AIRNO5q_nLdt8Ocug,19913
|
|
@@ -122,11 +117,11 @@ code_puppy/tui/models/enums.py,sha256=1ulsei95Gxy4r1sk-m-Sm5rdmejYCGRI-YtUwJmKFf
|
|
|
122
117
|
code_puppy/tui/screens/__init__.py,sha256=tJ00d0aYQ9kzOGHRChqy6cCQ6JUKKXBzLUTEbk_eA2Y,286
|
|
123
118
|
code_puppy/tui/screens/help.py,sha256=eJuPaOOCp7ZSUlecearqsuX6caxWv7NQszUh0tZJjBM,3232
|
|
124
119
|
code_puppy/tui/screens/mcp_install_wizard.py,sha256=vObpQwLbXjQsxmSg-WCasoev1usEi0pollKnL0SHu9U,27693
|
|
125
|
-
code_puppy/tui/screens/settings.py,sha256=
|
|
120
|
+
code_puppy/tui/screens/settings.py,sha256=W22sevojC1_HZBoeoJTH3HWkehini3bGi_ic0OKgeLI,10685
|
|
126
121
|
code_puppy/tui/screens/tools.py,sha256=3pr2Xkpa9Js6Yhf1A3_wQVRzFOui-KDB82LwrsdBtyk,1715
|
|
127
|
-
code_puppy-0.0.
|
|
128
|
-
code_puppy-0.0.
|
|
129
|
-
code_puppy-0.0.
|
|
130
|
-
code_puppy-0.0.
|
|
131
|
-
code_puppy-0.0.
|
|
132
|
-
code_puppy-0.0.
|
|
122
|
+
code_puppy-0.0.174.data/data/code_puppy/models.json,sha256=iXmLZGflnQcu2DRh4WUlgAhoXdvoxUc7KBhB8YxawXM,3088
|
|
123
|
+
code_puppy-0.0.174.dist-info/METADATA,sha256=cnh7U5TS6UOkwhUSw8Nek8vBxdinFzq-K7FO5FRZiIU,20103
|
|
124
|
+
code_puppy-0.0.174.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
125
|
+
code_puppy-0.0.174.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
|
|
126
|
+
code_puppy-0.0.174.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
127
|
+
code_puppy-0.0.174.dist-info/RECORD,,
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "agent-orchestrator-id",
|
|
3
|
-
"name": "agent-orchestrator",
|
|
4
|
-
"display_name": "Agent Orchestrator 🎭",
|
|
5
|
-
"description": "Coordinates and manages various specialized agents to accomplish tasks",
|
|
6
|
-
"system_prompt": [
|
|
7
|
-
"You are an agent orchestrator that coordinates various specialized agents.",
|
|
8
|
-
"When given a task, first list the available agents to understand what's at your disposal.",
|
|
9
|
-
"Then, invoke the most appropriate agent to handle the task. If needed, you can invoke multiple agents.",
|
|
10
|
-
"",
|
|
11
|
-
"#### `list_agents()`",
|
|
12
|
-
"Use this to list all available sub-agents that can be invoked",
|
|
13
|
-
"",
|
|
14
|
-
"#### `invoke_agent(agent_name: str, user_prompt: str)`",
|
|
15
|
-
"Use this to invoke another agent with a specific prompt. This allows agents to delegate tasks to specialized sub-agents.",
|
|
16
|
-
"Arguments:",
|
|
17
|
-
"- agent_name (required): Name of the agent to invoke",
|
|
18
|
-
"- user_prompt (required): The prompt to send to the invoked agent",
|
|
19
|
-
"Example usage:",
|
|
20
|
-
"```python",
|
|
21
|
-
"invoke_agent(agent_name=\"python-tutor\", user_prompt=\"Explain how to use list comprehensions\")",
|
|
22
|
-
"```"
|
|
23
|
-
],
|
|
24
|
-
"tools": ["list_agents", "invoke_agent", "agent_share_your_reasoning"],
|
|
25
|
-
"user_prompt": "What would you like me to coordinate for you?"
|
|
26
|
-
}
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Runtime agent manager that ensures proper agent instance updates.
|
|
3
|
-
|
|
4
|
-
This module provides a wrapper around the agent singleton that ensures
|
|
5
|
-
all references to the agent are properly updated when it's reloaded.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import asyncio
|
|
9
|
-
import signal
|
|
10
|
-
import sys
|
|
11
|
-
import uuid
|
|
12
|
-
from typing import Any, Optional
|
|
13
|
-
|
|
14
|
-
# ExceptionGroup is available in Python 3.11+
|
|
15
|
-
if sys.version_info >= (3, 11):
|
|
16
|
-
from builtins import ExceptionGroup
|
|
17
|
-
else:
|
|
18
|
-
# For Python 3.10 and below, we can define a simple fallback
|
|
19
|
-
class ExceptionGroup(Exception):
|
|
20
|
-
def __init__(self, message, exceptions):
|
|
21
|
-
super().__init__(message)
|
|
22
|
-
self.exceptions = exceptions
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
import mcp
|
|
26
|
-
from pydantic_ai import Agent
|
|
27
|
-
from pydantic_ai.exceptions import UsageLimitExceeded
|
|
28
|
-
from pydantic_ai.usage import UsageLimits
|
|
29
|
-
|
|
30
|
-
from code_puppy.messaging.message_queue import emit_info
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class RuntimeAgentManager:
|
|
34
|
-
"""
|
|
35
|
-
Manages the runtime agent instance and ensures proper updates.
|
|
36
|
-
|
|
37
|
-
This class acts as a proxy that always returns the current agent instance,
|
|
38
|
-
ensuring that when the agent is reloaded, all code using this manager
|
|
39
|
-
automatically gets the updated instance.
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
def __init__(self):
|
|
43
|
-
"""Initialize the runtime agent manager."""
|
|
44
|
-
self._agent: Optional[Agent] = None
|
|
45
|
-
self._last_model_name: Optional[str] = None
|
|
46
|
-
|
|
47
|
-
def get_agent(self, force_reload: bool = False, message_group: str = "") -> Agent:
|
|
48
|
-
"""
|
|
49
|
-
Get the current agent instance.
|
|
50
|
-
|
|
51
|
-
This method always returns the most recent agent instance,
|
|
52
|
-
automatically handling reloads when the model changes.
|
|
53
|
-
|
|
54
|
-
Args:
|
|
55
|
-
force_reload: If True, force a reload of the agent
|
|
56
|
-
|
|
57
|
-
Returns:
|
|
58
|
-
The current agent instance
|
|
59
|
-
"""
|
|
60
|
-
from code_puppy.agent import get_code_generation_agent
|
|
61
|
-
|
|
62
|
-
# Always get the current singleton - this ensures we have the latest
|
|
63
|
-
current_agent = get_code_generation_agent(
|
|
64
|
-
force_reload=force_reload, message_group=message_group
|
|
65
|
-
)
|
|
66
|
-
self._agent = current_agent
|
|
67
|
-
|
|
68
|
-
return self._agent
|
|
69
|
-
|
|
70
|
-
def reload_agent(self) -> Agent:
|
|
71
|
-
"""
|
|
72
|
-
Force reload the agent.
|
|
73
|
-
|
|
74
|
-
This is typically called after MCP servers are started/stopped.
|
|
75
|
-
|
|
76
|
-
Returns:
|
|
77
|
-
The newly loaded agent instance
|
|
78
|
-
"""
|
|
79
|
-
message_group = uuid.uuid4()
|
|
80
|
-
emit_info(
|
|
81
|
-
"[bold cyan]Reloading agent with updated configuration...[/bold cyan]",
|
|
82
|
-
message_group=message_group,
|
|
83
|
-
)
|
|
84
|
-
return self.get_agent(force_reload=True, message_group=message_group)
|
|
85
|
-
|
|
86
|
-
async def run_with_mcp(
|
|
87
|
-
self, prompt: str, usage_limits: Optional[UsageLimits] = None, **kwargs
|
|
88
|
-
) -> Any:
|
|
89
|
-
"""
|
|
90
|
-
Run the agent with MCP servers and full cancellation support.
|
|
91
|
-
|
|
92
|
-
This method ensures we're always using the current agent instance
|
|
93
|
-
and handles Ctrl+C interruption properly by creating a cancellable task.
|
|
94
|
-
|
|
95
|
-
Args:
|
|
96
|
-
prompt: The user prompt to process
|
|
97
|
-
usage_limits: Optional usage limits for the agent
|
|
98
|
-
**kwargs: Additional arguments to pass to agent.run (e.g., message_history)
|
|
99
|
-
|
|
100
|
-
Returns:
|
|
101
|
-
The agent's response
|
|
102
|
-
|
|
103
|
-
Raises:
|
|
104
|
-
asyncio.CancelledError: When execution is cancelled by user
|
|
105
|
-
"""
|
|
106
|
-
agent = self.get_agent()
|
|
107
|
-
group_id = str(uuid.uuid4())
|
|
108
|
-
|
|
109
|
-
# Function to run agent with MCP
|
|
110
|
-
async def run_agent_task():
|
|
111
|
-
try:
|
|
112
|
-
async with agent:
|
|
113
|
-
return await agent.run(prompt, usage_limits=usage_limits, **kwargs)
|
|
114
|
-
except* UsageLimitExceeded as ule:
|
|
115
|
-
emit_info(f"Usage limit exceeded: {str(ule)}", group_id=group_id)
|
|
116
|
-
emit_info(
|
|
117
|
-
"The agent has reached its usage limit. You can ask it to continue by saying 'please continue' or similar.",
|
|
118
|
-
group_id=group_id,
|
|
119
|
-
)
|
|
120
|
-
except* mcp.shared.exceptions.McpError as mcp_error:
|
|
121
|
-
emit_info(f"MCP server error: {str(mcp_error)}", group_id=group_id)
|
|
122
|
-
emit_info(f"{str(mcp_error)}", group_id=group_id)
|
|
123
|
-
emit_info(
|
|
124
|
-
"Try disabling any malfunctioning MCP servers", group_id=group_id
|
|
125
|
-
)
|
|
126
|
-
except* asyncio.exceptions.CancelledError:
|
|
127
|
-
emit_info("Cancelled")
|
|
128
|
-
except* InterruptedError as ie:
|
|
129
|
-
emit_info(f"Interrupted: {str(ie)}")
|
|
130
|
-
except* Exception as other_error:
|
|
131
|
-
# Filter out CancelledError and UsageLimitExceeded from the exception group - let it propagate
|
|
132
|
-
remaining_exceptions = []
|
|
133
|
-
|
|
134
|
-
def collect_non_cancelled_exceptions(exc):
|
|
135
|
-
if isinstance(exc, ExceptionGroup):
|
|
136
|
-
for sub_exc in exc.exceptions:
|
|
137
|
-
collect_non_cancelled_exceptions(sub_exc)
|
|
138
|
-
elif not isinstance(
|
|
139
|
-
exc, (asyncio.CancelledError, UsageLimitExceeded)
|
|
140
|
-
):
|
|
141
|
-
remaining_exceptions.append(exc)
|
|
142
|
-
emit_info(f"Unexpected error: {str(exc)}", group_id=group_id)
|
|
143
|
-
emit_info(f"{str(exc.args)}", group_id=group_id)
|
|
144
|
-
|
|
145
|
-
collect_non_cancelled_exceptions(other_error)
|
|
146
|
-
|
|
147
|
-
# If there are CancelledError exceptions in the group, re-raise them
|
|
148
|
-
cancelled_exceptions = []
|
|
149
|
-
|
|
150
|
-
def collect_cancelled_exceptions(exc):
|
|
151
|
-
if isinstance(exc, ExceptionGroup):
|
|
152
|
-
for sub_exc in exc.exceptions:
|
|
153
|
-
collect_cancelled_exceptions(sub_exc)
|
|
154
|
-
elif isinstance(exc, asyncio.CancelledError):
|
|
155
|
-
cancelled_exceptions.append(exc)
|
|
156
|
-
|
|
157
|
-
collect_cancelled_exceptions(other_error)
|
|
158
|
-
|
|
159
|
-
if cancelled_exceptions:
|
|
160
|
-
# Re-raise the first CancelledError to propagate cancellation
|
|
161
|
-
raise cancelled_exceptions[0]
|
|
162
|
-
|
|
163
|
-
# Create the task FIRST
|
|
164
|
-
agent_task = asyncio.create_task(run_agent_task())
|
|
165
|
-
|
|
166
|
-
# Import shell process killer
|
|
167
|
-
from code_puppy.tools.command_runner import kill_all_running_shell_processes
|
|
168
|
-
|
|
169
|
-
# Ensure the interrupt handler only acts once per task
|
|
170
|
-
def keyboard_interrupt_handler(sig, frame):
|
|
171
|
-
"""Signal handler for Ctrl+C - replicating exact original logic"""
|
|
172
|
-
|
|
173
|
-
# First, nuke any running shell processes triggered by tools
|
|
174
|
-
try:
|
|
175
|
-
killed = kill_all_running_shell_processes()
|
|
176
|
-
if killed:
|
|
177
|
-
emit_info(f"Cancelled {killed} running shell process(es).")
|
|
178
|
-
else:
|
|
179
|
-
# Only cancel the agent task if no shell processes were killed
|
|
180
|
-
if not agent_task.done():
|
|
181
|
-
agent_task.cancel()
|
|
182
|
-
except Exception as e:
|
|
183
|
-
emit_info(f"Shell kill error: {e}")
|
|
184
|
-
# If shell kill failed, still try to cancel the agent task
|
|
185
|
-
if not agent_task.done():
|
|
186
|
-
agent_task.cancel()
|
|
187
|
-
# Don't call the original handler
|
|
188
|
-
# This prevents the application from exiting
|
|
189
|
-
|
|
190
|
-
try:
|
|
191
|
-
# Save original handler and set our custom one AFTER task is created
|
|
192
|
-
original_handler = signal.signal(signal.SIGINT, keyboard_interrupt_handler)
|
|
193
|
-
|
|
194
|
-
# Wait for the task to complete or be cancelled
|
|
195
|
-
result = await agent_task
|
|
196
|
-
return result
|
|
197
|
-
except asyncio.CancelledError:
|
|
198
|
-
# Task was cancelled by our handler
|
|
199
|
-
raise
|
|
200
|
-
except KeyboardInterrupt:
|
|
201
|
-
# Handle direct keyboard interrupt during await
|
|
202
|
-
if not agent_task.done():
|
|
203
|
-
agent_task.cancel()
|
|
204
|
-
try:
|
|
205
|
-
await agent_task
|
|
206
|
-
except asyncio.CancelledError:
|
|
207
|
-
pass
|
|
208
|
-
raise asyncio.CancelledError()
|
|
209
|
-
finally:
|
|
210
|
-
# Restore original signal handler
|
|
211
|
-
if original_handler:
|
|
212
|
-
signal.signal(signal.SIGINT, original_handler)
|
|
213
|
-
|
|
214
|
-
async def run(
|
|
215
|
-
self, prompt: str, usage_limits: Optional[UsageLimits] = None, **kwargs
|
|
216
|
-
) -> Any:
|
|
217
|
-
"""
|
|
218
|
-
Run the agent without explicitly managing MCP servers.
|
|
219
|
-
|
|
220
|
-
Args:
|
|
221
|
-
prompt: The user prompt to process
|
|
222
|
-
usage_limits: Optional usage limits for the agent
|
|
223
|
-
**kwargs: Additional arguments to pass to agent.run (e.g., message_history)
|
|
224
|
-
|
|
225
|
-
Returns:
|
|
226
|
-
The agent's response
|
|
227
|
-
"""
|
|
228
|
-
agent = self.get_agent()
|
|
229
|
-
try:
|
|
230
|
-
return await agent.run(prompt, usage_limits=usage_limits, **kwargs)
|
|
231
|
-
except UsageLimitExceeded as ule:
|
|
232
|
-
group_id = str(uuid.uuid4())
|
|
233
|
-
emit_info(f"Usage limit exceeded: {str(ule)}", group_id=group_id)
|
|
234
|
-
emit_info(
|
|
235
|
-
"The agent has reached its usage limit. You can ask it to continue by saying 'please continue' or similar.",
|
|
236
|
-
group_id=group_id,
|
|
237
|
-
)
|
|
238
|
-
# Return None or some default value to indicate the limit was reached
|
|
239
|
-
return None
|
|
240
|
-
|
|
241
|
-
def __getattr__(self, name: str) -> Any:
|
|
242
|
-
"""
|
|
243
|
-
Proxy all other attribute access to the current agent.
|
|
244
|
-
|
|
245
|
-
This allows the manager to be used as a drop-in replacement
|
|
246
|
-
for direct agent access.
|
|
247
|
-
|
|
248
|
-
Args:
|
|
249
|
-
name: The attribute name to access
|
|
250
|
-
|
|
251
|
-
Returns:
|
|
252
|
-
The attribute from the current agent
|
|
253
|
-
"""
|
|
254
|
-
agent = self.get_agent()
|
|
255
|
-
return getattr(agent, name)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
# Global singleton instance
|
|
259
|
-
_runtime_manager: Optional[RuntimeAgentManager] = None
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
def get_runtime_agent_manager() -> RuntimeAgentManager:
|
|
263
|
-
"""
|
|
264
|
-
Get the global runtime agent manager instance.
|
|
265
|
-
|
|
266
|
-
Returns:
|
|
267
|
-
The singleton RuntimeAgentManager instance
|
|
268
|
-
"""
|
|
269
|
-
global _runtime_manager
|
|
270
|
-
if _runtime_manager is None:
|
|
271
|
-
_runtime_manager = RuntimeAgentManager()
|
|
272
|
-
return _runtime_manager
|