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.
Files changed (29) hide show
  1. code_puppy/agent.py +11 -11
  2. code_puppy/agents/__init__.py +4 -6
  3. code_puppy/agents/agent_manager.py +15 -187
  4. code_puppy/agents/base_agent.py +470 -63
  5. code_puppy/command_line/command_handler.py +40 -41
  6. code_puppy/command_line/mcp/start_all_command.py +3 -6
  7. code_puppy/command_line/mcp/start_command.py +0 -5
  8. code_puppy/command_line/mcp/stop_all_command.py +3 -6
  9. code_puppy/command_line/mcp/stop_command.py +2 -6
  10. code_puppy/command_line/model_picker_completion.py +2 -2
  11. code_puppy/command_line/prompt_toolkit_completion.py +2 -2
  12. code_puppy/config.py +2 -2
  13. code_puppy/main.py +12 -49
  14. code_puppy/summarization_agent.py +2 -2
  15. code_puppy/tools/agent_tools.py +5 -4
  16. code_puppy/tools/browser/vqa_agent.py +1 -3
  17. code_puppy/tui/app.py +48 -77
  18. code_puppy/tui/screens/settings.py +2 -2
  19. {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/METADATA +2 -2
  20. {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/RECORD +24 -29
  21. code_puppy/agents/agent_orchestrator.json +0 -26
  22. code_puppy/agents/runtime_manager.py +0 -272
  23. code_puppy/command_line/meta_command_handler.py +0 -153
  24. code_puppy/message_history_processor.py +0 -408
  25. code_puppy/state_management.py +0 -58
  26. {code_puppy-0.0.173.data → code_puppy-0.0.174.data}/data/code_puppy/models.json +0 -0
  27. {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/WHEEL +0 -0
  28. {code_puppy-0.0.173.dist-info → code_puppy-0.0.174.dist-info}/entry_points.txt +0 -0
  29. {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
- get_model_name,
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
- from code_puppy.message_history_processor import (
25
- message_history_accumulator,
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
- from code_puppy.state_management import (
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 get_current_agent_config
106
+ from code_puppy.agents.agent_manager import get_current_agent
116
107
 
117
- current_agent_config = get_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 = get_model_name()
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 get_current_agent_config
156
+ from code_puppy.agents.agent_manager import get_current_agent
167
157
 
168
- current_agent_config = get_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
- get_code_generation_agent()
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
- if self.agent_manager:
495
- try:
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
- except Exception as eg:
523
- # Handle TaskGroup and other exceptions
524
- # BaseExceptionGroup is only available in Python 3.11+
525
- if hasattr(eg, "exceptions"):
526
- # Handle TaskGroup exceptions specifically (Python 3.11+)
527
- for e in eg.exceptions:
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
- else:
542
- self.add_error_message("Agent manager not initialized")
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 get_model_name, get_puppy_name
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 = get_model_name()
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
- get_model_name,
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 = get_model_name()
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.173
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>=1.0.10
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=rBe7OS_ekZvMuteLuIp9lor9zIP7KHBsxZ22pWM9_fg,8526
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=A3l5gSJGz9kGXJb2pZVyoksDGclIhMdKmAv-EdDSleY,20625
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=VlH8fXPapXblSagOjrezeSTtFij_-X3dzq1cfHPXwDI,22252
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=kos4_YK-l_YjYRq4Fs4X5YoTUbmAcDhhPqefL-rdenI,3197
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=SwtHGNG1GIgDBv7y3EGIXOXEWrG_Ou7fEknNgFbrHv8,594
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=nXvro6fpX8KA-NedRoVJuhJW966trrePOrH4eAnqq40,17034
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=XUsziIf0ZGCe6ZLjt-kJqbeYTy9gTQE3_BPq7THQ3X8,19538
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=45jUScWIikVi2OgCL7LrcpWoDcrmfWv0do-y_mS4i8U,27248
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/meta_command_handler.py,sha256=80aK5JQOaqjt149qBmSsM02uy2Cikkee8zaQnu5u2KQ,5712
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=PLb1Yt_65iQI2mzPEPxPsSaRww5Ur951Qn-K-TLMCGQ,10006
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=9f8BPTijs7BVBQKKNXjtH3laQVuqhNyfPSgISvBUcfM,4295
48
- code_puppy/command_line/mcp/start_command.py,sha256=r00onOpfSSL-gtJLDOvmD-8G4RZhhmd-nv3TyIWGMUI,3350
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=QioqCPFjIbbdT_P5tyVakB2idUD1rnlhwYXLpa-G4TI,3716
51
- code_puppy/command_line/mcp/stop_command.py,sha256=zuZO8pIP2Ix11LATf-cwwX3fPFIGAbRDaZ6qnfPTqLY,2594
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=bHMrFIbYRhuubR41G_XdLsk3cUKWfIPl2O4bVzo2pE0,5591
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=u3EhZQHNBiWUn-XLDK9MnVyd2ChshPnVZbB9iEkEqH4,2118
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=WW-O8myM_yl05NIdj_aSp7zN56AwimgdMA9TmEOE54Y,39427
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=GMpv-qa08rorAE9mj3AjmqjZFPhmeJ_GWd-DBHG6iAA,10671
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.173.data/data/code_puppy/models.json,sha256=iXmLZGflnQcu2DRh4WUlgAhoXdvoxUc7KBhB8YxawXM,3088
128
- code_puppy-0.0.173.dist-info/METADATA,sha256=4qImoiksA3Y_7gc-YlHc7cAdJJa6pnP2xhOUQbQ9vCY,20106
129
- code_puppy-0.0.173.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
130
- code_puppy-0.0.173.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
131
- code_puppy-0.0.173.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
132
- code_puppy-0.0.173.dist-info/RECORD,,
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