code-puppy 0.0.178__py3-none-any.whl → 0.0.180__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.
@@ -829,15 +829,15 @@ class BaseAgent(ABC):
829
829
 
830
830
  async def run_agent_task():
831
831
  try:
832
+ self.set_message_history(
833
+ self.prune_interrupted_tool_calls(self.get_message_history())
834
+ )
832
835
  result_ = await pydantic_agent.run(
833
836
  prompt,
834
837
  message_history=self.get_message_history(),
835
838
  usage_limits=usage_limits,
836
839
  **kwargs,
837
840
  )
838
- self.set_message_history(
839
- self.prune_interrupted_tool_calls(self.get_message_history())
840
- )
841
841
  return result_
842
842
  except* UsageLimitExceeded as ule:
843
843
  emit_info(f"Usage limit exceeded: {str(ule)}", group_id=group_id)
@@ -883,10 +883,10 @@ class BaseAgent(ABC):
883
883
  cancelled_exceptions.append(exc)
884
884
 
885
885
  collect_cancelled_exceptions(other_error)
886
-
887
- if cancelled_exceptions:
888
- # Re-raise the first CancelledError to propagate cancellation
889
- raise cancelled_exceptions[0]
886
+ finally:
887
+ self.set_message_history(
888
+ self.prune_interrupted_tool_calls(self.get_message_history())
889
+ )
890
890
 
891
891
  # Create the task FIRST
892
892
  agent_task = asyncio.create_task(run_agent_task())
@@ -909,7 +909,6 @@ class BaseAgent(ABC):
909
909
  agent_task.cancel()
910
910
  except Exception as e:
911
911
  emit_info(f"Shell kill error: {e}")
912
- # If shell kill failed, still try to cancel the agent task
913
912
  if not agent_task.done():
914
913
  agent_task.cancel()
915
914
  # Don't call the original handler
@@ -923,8 +922,7 @@ class BaseAgent(ABC):
923
922
  result = await agent_task
924
923
  return result
925
924
  except asyncio.CancelledError:
926
- # Task was cancelled by our handler
927
- raise
925
+ agent_task.cancel()
928
926
  except KeyboardInterrupt:
929
927
  # Handle direct keyboard interrupt during await
930
928
  if not agent_task.done():
@@ -933,7 +931,6 @@ class BaseAgent(ABC):
933
931
  await agent_task
934
932
  except asyncio.CancelledError:
935
933
  pass
936
- raise asyncio.CancelledError()
937
934
  finally:
938
935
  # Restore original signal handler
939
936
  if original_handler:
code_puppy/main.py CHANGED
@@ -383,6 +383,8 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
383
383
  if task.strip().lower() in ("clear", "/clear"):
384
384
  from code_puppy.messaging import emit_system_message, emit_warning
385
385
 
386
+ agent = get_current_agent()
387
+ agent.clear_message_history()
386
388
  emit_warning("Conversation history cleared!")
387
389
  emit_system_message("The agent will not remember previous interactions.\n")
388
390
  continue
code_puppy/tui/app.py CHANGED
@@ -515,6 +515,8 @@ class CodePuppyTUI(App):
515
515
  """Clear the chat history."""
516
516
  chat_view = self.query_one("#chat-view", ChatView)
517
517
  chat_view.clear_messages()
518
+ agent = get_current_agent()
519
+ agent.clear_message_history()
518
520
  self.add_system_message("Chat history cleared")
519
521
 
520
522
  def action_show_help(self) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-puppy
3
- Version: 0.0.178
3
+ Version: 0.0.180
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
@@ -3,7 +3,7 @@ code_puppy/__main__.py,sha256=pDVssJOWP8A83iFkxMLY9YteHYat0EyWDQqMkKHpWp4,203
3
3
  code_puppy/callbacks.py,sha256=6wYB6K_fGSCkKKEFaYOYkJT45WaV5W_NhUIzcvVH_nU,5060
4
4
  code_puppy/config.py,sha256=smjGUs18VJQxPeVLvV8U2T_YuGh7E_Sg5ZgaXhdBWWg,20677
5
5
  code_puppy/http_utils.py,sha256=YLd8Y16idbI32JGeBXG8n5rT4o4X_zxk9FgUvK9XFo8,8248
6
- code_puppy/main.py,sha256=c5nxJ6eRve9KFFTxVtioWJ393e6sxy7quld9TQpsH94,20519
6
+ code_puppy/main.py,sha256=_TvwZFFepyq6UCC29ApFUeXeODsRHV2OyFuzM3xkiwo,20601
7
7
  code_puppy/model_factory.py,sha256=KLyxUrZJual6uo_TncjdPhdDbvIvHiztWvK9bfdQmmc,13759
8
8
  code_puppy/models.json,sha256=iXmLZGflnQcu2DRh4WUlgAhoXdvoxUc7KBhB8YxawXM,3088
9
9
  code_puppy/reopenable_async_client.py,sha256=4UJRaMp5np8cbef9F0zKQ7TPKOfyf5U-Kv-0zYUWDho,8274
@@ -13,12 +13,20 @@ code_puppy/summarization_agent.py,sha256=LnObgtLmM6N4z2553XXQlXAOf8R1BPSNmFSfXkj
13
13
  code_puppy/tui_state.py,sha256=TT76XBVapKj6fKjFzz6oxCONeN_BZwcMILxxZcxu6-Y,1171
14
14
  code_puppy/version_checker.py,sha256=bjLDmgGPrl7XnYwX1u13O8uFlsfikV90PK6nbA9Z9QU,1150
15
15
  code_puppy/agents/__init__.py,sha256=PtPB7Z5MSwmUKipgt_qxvIuGggcuVaYwNbnp1UP4tPc,518
16
+ code_puppy/agents/agent_c_reviewer.py,sha256=XVOONfnbCS6nEdcXoiowuSB5pnqrXyoWIAjG2cKm7BU,5044
16
17
  code_puppy/agents/agent_code_puppy.py,sha256=vk25J5YSjt30ItfML8KyQc5QR8QumBv5_U8RhqaXUz4,7973
18
+ code_puppy/agents/agent_code_reviewer.py,sha256=8XHktiFrOVeFZ81WIefuTPQw_IzcNddm4bk46mW46ok,4003
19
+ code_puppy/agents/agent_cpp_reviewer.py,sha256=H4INgJo2OJ84QT7bfTkw4s1Ml7luwokhAgTsdig2TQQ,3653
17
20
  code_puppy/agents/agent_creator_agent.py,sha256=IiwVirB6uoIeGOmtetut9eDv6o055ykND3V-fvyA8Lw,23042
18
- code_puppy/agents/agent_golang_reviewer.py,sha256=cdJEK0J5oZEIW9Sw5Hj_FiVP0iN-_NoAnjP4b6xB_Rw,3308
21
+ code_puppy/agents/agent_golang_reviewer.py,sha256=-OMuT8hkapVf2Oox46Ck9SRHlsfd8ab8uefbVfdW72M,3348
22
+ code_puppy/agents/agent_javascript_reviewer.py,sha256=5YC4kRSvorcNgObjHjD2Rrgnvf8jlKhPqWdjOMjU9A0,3636
19
23
  code_puppy/agents/agent_manager.py,sha256=USzTbsGGZ9CH17LFeb6P6Im8RPY8qZUGKoH9EZZyU3k,11413
24
+ code_puppy/agents/agent_python_reviewer.py,sha256=D0M3VA12QKdsyg2zIBI2FECxz0IP2fSIfg24xGzDhw0,3837
25
+ code_puppy/agents/agent_qa_expert.py,sha256=wCGXzuAVElT5c-QigQVb8JX9Gw0JmViCUQQnADMSbVc,3796
20
26
  code_puppy/agents/agent_qa_kitten.py,sha256=5PeFFSwCFlTUvP6h5bGntx0xv5NmRwBiw0HnMqY8nLI,9107
21
- code_puppy/agents/base_agent.py,sha256=Ld9WTYPMr2uewivHmjBr99L6vlkR1F7jdlz6XG_ZBUQ,37155
27
+ code_puppy/agents/agent_security_auditor.py,sha256=ADafi2x4gqXw6m-Nch5vjiKjO0Urcbj0x4zxHti3gDw,3712
28
+ code_puppy/agents/agent_typescript_reviewer.py,sha256=EDY1mFkVpuJ1BPXsJFu2wQ2pfAV-90ipc_8w9ymrKPg,4054
29
+ code_puppy/agents/base_agent.py,sha256=MFyC4YSxlQ1xzQRBnSXgtyO7XPpHZuSJVzRATU8j7J0,36992
22
30
  code_puppy/agents/json_agent.py,sha256=y6AYE3Fx9LhmemcPzt46d7359MNnkGIjU83YBGNer2g,4533
23
31
  code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
24
32
  code_puppy/command_line/command_handler.py,sha256=JeJo6kc9-4B7S0_pbMp1LO7jtAT6XMXtSSnOShfoG-Y,27237
@@ -75,13 +83,6 @@ code_puppy/messaging/spinner/textual_spinner.py,sha256=Omx9A-FSPkxYDMYgBXgYMBQnK
75
83
  code_puppy/plugins/__init__.py,sha256=fksDqMUiXPJ5WNuMsYsVR8ulueQRCXPlvECEyicHPtQ,1312
76
84
  code_puppy/tools/__init__.py,sha256=BVTZ85jLHgDANwOnUSOz3UDlp8VQDq4DoGF23BRlyWw,6032
77
85
  code_puppy/tools/agent_tools.py,sha256=VMTKPfNUiK90ifyJUtEvUpOHmmifpWCxDKv7j6oTaxI,5620
78
- code_puppy/tools/browser_control.py,sha256=6E_Kq63cErBk-iM9-03Cq8sTWWLh-Tk2kpdrB_rMmbg,8603
79
- code_puppy/tools/browser_interactions.py,sha256=m-bVsAUbdrS-P1GbS0ChO2tMMg4tMIsDX34azn_Olzs,17070
80
- code_puppy/tools/browser_locators.py,sha256=ZshjhYuV600vJqXUC23oNX89AZLMvY8rlvj-9oy7GMw,19574
81
- code_puppy/tools/browser_navigation.py,sha256=Tj_fNcM3KGpkM2UTKcGQX8BpI373Sv7xZAJf-U7pO5M,7621
82
- code_puppy/tools/browser_screenshot.py,sha256=QSwxS37G4LSo-Q9SBiuIofxWKnyInM90TY-_fiWQLrs,9222
83
- code_puppy/tools/browser_scripts.py,sha256=MMO5KRjdrhuLOoJGoKGG1jm6UAqhFhUznz02aWqhMAE,15065
84
- code_puppy/tools/browser_workflows.py,sha256=SJfiM2SgZr-qeeQJEivGzUNc51AlLIoqj9h1-mTvVsA,6593
85
86
  code_puppy/tools/command_runner.py,sha256=SRhTACgKklHUm_ztbFHnefGbLw4CJOm601or6L1cPGM,22417
86
87
  code_puppy/tools/common.py,sha256=pL-9xcRs3rxU7Fl9X9EUgbDp2-csh2LLJ5DHH_KAHKY,10596
87
88
  code_puppy/tools/file_modifications.py,sha256=EaDWcv6gi8wAvpgyeJdKSKPWg9fTpZoEkxQiLCE6rn4,23218
@@ -98,7 +99,7 @@ code_puppy/tools/browser/browser_workflows.py,sha256=jplJ1T60W3G4-dhVJX-CXkm9ssk
98
99
  code_puppy/tools/browser/camoufox_manager.py,sha256=RYvLcs0iAoVNtpLjrrA1uu6a5k9tAdBbmhWFGSWjX_A,6106
99
100
  code_puppy/tools/browser/vqa_agent.py,sha256=0GMDgJAK728rIuSQxAVytFSNagjo0LCjCUxBTm3w9Po,1952
100
101
  code_puppy/tui/__init__.py,sha256=XesAxIn32zLPOmvpR2wIDxDAnnJr81a5pBJB4cZp1Xs,321
101
- code_puppy/tui/app.py,sha256=f_8c9t9WF1twn4GCNNnmEgklSyUDC-9-d8_Lkosszjk,37911
102
+ code_puppy/tui/app.py,sha256=fiOKrhtYBpruUPM-aqnsDmEiOM_dCbD5DnBRKO219NI,37985
102
103
  code_puppy/tui/messages.py,sha256=zQoToWI0eWdT36NEsY6RdCFzcDfAmfvoPlHv8jiCbgo,720
103
104
  code_puppy/tui/components/__init__.py,sha256=uj5pnk3s6SEN3SbFI0ZnzaA2KK1NNg8TfUj6U-Z732U,455
104
105
  code_puppy/tui/components/chat_view.py,sha256=Ff6uM6J0yENISNAOYroX7F-JL73_ajUUcP5IZSf2mng,19914
@@ -118,9 +119,9 @@ code_puppy/tui/screens/help.py,sha256=eJuPaOOCp7ZSUlecearqsuX6caxWv7NQszUh0tZJjB
118
119
  code_puppy/tui/screens/mcp_install_wizard.py,sha256=vObpQwLbXjQsxmSg-WCasoev1usEi0pollKnL0SHu9U,27693
119
120
  code_puppy/tui/screens/settings.py,sha256=-WLldnKyWVKUYVPJcfOn1UU6eP9t8lLPUAVI317SOOM,10685
120
121
  code_puppy/tui/screens/tools.py,sha256=3pr2Xkpa9Js6Yhf1A3_wQVRzFOui-KDB82LwrsdBtyk,1715
121
- code_puppy-0.0.178.data/data/code_puppy/models.json,sha256=iXmLZGflnQcu2DRh4WUlgAhoXdvoxUc7KBhB8YxawXM,3088
122
- code_puppy-0.0.178.dist-info/METADATA,sha256=sn-XrM1AZoJQWMYG6YSkGknl0cmfCjfLOdb6NLEMzYE,20079
123
- code_puppy-0.0.178.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
124
- code_puppy-0.0.178.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
125
- code_puppy-0.0.178.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
126
- code_puppy-0.0.178.dist-info/RECORD,,
122
+ code_puppy-0.0.180.data/data/code_puppy/models.json,sha256=iXmLZGflnQcu2DRh4WUlgAhoXdvoxUc7KBhB8YxawXM,3088
123
+ code_puppy-0.0.180.dist-info/METADATA,sha256=vYolNp6ezYwpXSXhhzSdt_6GZdqFOOMVutES6BiN5jM,20079
124
+ code_puppy-0.0.180.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
125
+ code_puppy-0.0.180.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
126
+ code_puppy-0.0.180.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
127
+ code_puppy-0.0.180.dist-info/RECORD,,
@@ -1,293 +0,0 @@
1
- """Browser initialization and control tools."""
2
-
3
- from typing import Any, Dict, Optional
4
-
5
- from pydantic_ai import RunContext
6
-
7
- from code_puppy.messaging import emit_info
8
- from code_puppy.tools.common import generate_group_id
9
-
10
- from .camoufox_manager import get_camoufox_manager
11
-
12
-
13
- async def initialize_browser(
14
- headless: bool = False,
15
- browser_type: str = "chromium",
16
- homepage: str = "https://www.google.com",
17
- ) -> Dict[str, Any]:
18
- """Initialize the browser with specified settings."""
19
- group_id = generate_group_id("browser_initialize", f"{browser_type}_{homepage}")
20
- emit_info(
21
- f"[bold white on blue] BROWSER INITIALIZE [/bold white on blue] 🌐 {browser_type} → {homepage}",
22
- message_group=group_id,
23
- )
24
- try:
25
- browser_manager = get_camoufox_manager()
26
-
27
- # Configure browser settings
28
- browser_manager.headless = headless
29
- browser_manager.browser_type = browser_type
30
- browser_manager.homepage = homepage
31
-
32
- # Initialize browser
33
- await browser_manager.async_initialize()
34
-
35
- # Get page info
36
- page = await browser_manager.get_current_page()
37
- if page:
38
- url = page.url
39
- title = await page.title()
40
- else:
41
- url = "Unknown"
42
- title = "Unknown"
43
-
44
- emit_info(
45
- "[green]Browser initialized successfully[/green]", message_group=group_id
46
- )
47
-
48
- return {
49
- "success": True,
50
- "browser_type": browser_type,
51
- "headless": headless,
52
- "homepage": homepage,
53
- "current_url": url,
54
- "current_title": title,
55
- }
56
-
57
- except Exception as e:
58
- emit_info(
59
- f"[red]Browser initialization failed: {str(e)}[/red]",
60
- message_group=group_id,
61
- )
62
- return {
63
- "success": False,
64
- "error": str(e),
65
- "browser_type": browser_type,
66
- "headless": headless,
67
- }
68
-
69
-
70
- async def close_browser() -> Dict[str, Any]:
71
- """Close the browser and clean up resources."""
72
- group_id = generate_group_id("browser_close")
73
- emit_info(
74
- "[bold white on blue] BROWSER CLOSE [/bold white on blue] 🔒",
75
- message_group=group_id,
76
- )
77
- try:
78
- browser_manager = get_camoufox_manager()
79
- await browser_manager.close()
80
-
81
- emit_info(
82
- "[yellow]Browser closed successfully[/yellow]", message_group=group_id
83
- )
84
-
85
- return {"success": True, "message": "Browser closed"}
86
-
87
- except Exception as e:
88
- return {"success": False, "error": str(e)}
89
-
90
-
91
- async def get_browser_status() -> Dict[str, Any]:
92
- """Get current browser status and information."""
93
- group_id = generate_group_id("browser_status")
94
- emit_info(
95
- "[bold white on blue] BROWSER STATUS [/bold white on blue] 📊",
96
- message_group=group_id,
97
- )
98
- try:
99
- browser_manager = get_camoufox_manager()
100
-
101
- if not browser_manager._initialized:
102
- return {
103
- "success": True,
104
- "status": "not_initialized",
105
- "browser_type": browser_manager.browser_type,
106
- "headless": browser_manager.headless,
107
- }
108
-
109
- page = await browser_manager.get_current_page()
110
- if page:
111
- url = page.url
112
- title = await page.title()
113
-
114
- # Get all pages
115
- all_pages = await browser_manager.get_all_pages()
116
- page_count = len(all_pages)
117
- else:
118
- url = None
119
- title = None
120
- page_count = 0
121
-
122
- return {
123
- "success": True,
124
- "status": "initialized",
125
- "browser_type": browser_manager.browser_type,
126
- "headless": browser_manager.headless,
127
- "current_url": url,
128
- "current_title": title,
129
- "page_count": page_count,
130
- }
131
-
132
- except Exception as e:
133
- return {"success": False, "error": str(e)}
134
-
135
-
136
- async def create_new_page(url: Optional[str] = None) -> Dict[str, Any]:
137
- """Create a new browser page/tab."""
138
- group_id = generate_group_id("browser_new_page", url or "blank")
139
- emit_info(
140
- f"[bold white on blue] BROWSER NEW PAGE [/bold white on blue] 📄 {url or 'blank page'}",
141
- message_group=group_id,
142
- )
143
- try:
144
- browser_manager = get_camoufox_manager()
145
-
146
- if not browser_manager._initialized:
147
- return {
148
- "success": False,
149
- "error": "Browser not initialized. Use browser_initialize first.",
150
- }
151
-
152
- page = await browser_manager.new_page(url)
153
-
154
- final_url = page.url
155
- title = await page.title()
156
-
157
- emit_info(
158
- f"[green]Created new page: {final_url}[/green]", message_group=group_id
159
- )
160
-
161
- return {"success": True, "url": final_url, "title": title, "requested_url": url}
162
-
163
- except Exception as e:
164
- return {"success": False, "error": str(e), "url": url}
165
-
166
-
167
- async def list_pages() -> Dict[str, Any]:
168
- """List all open browser pages/tabs."""
169
- group_id = generate_group_id("browser_list_pages")
170
- emit_info(
171
- "[bold white on blue] BROWSER LIST PAGES [/bold white on blue] 📋",
172
- message_group=group_id,
173
- )
174
- try:
175
- browser_manager = get_camoufox_manager()
176
-
177
- if not browser_manager._initialized:
178
- return {"success": False, "error": "Browser not initialized"}
179
-
180
- all_pages = await browser_manager.get_all_pages()
181
-
182
- pages_info = []
183
- for i, page in enumerate(all_pages):
184
- try:
185
- url = page.url
186
- title = await page.title()
187
- is_closed = page.is_closed()
188
-
189
- pages_info.append(
190
- {"index": i, "url": url, "title": title, "closed": is_closed}
191
- )
192
- except Exception as e:
193
- pages_info.append(
194
- {
195
- "index": i,
196
- "url": "Error",
197
- "title": "Error",
198
- "error": str(e),
199
- "closed": True,
200
- }
201
- )
202
-
203
- return {"success": True, "page_count": len(all_pages), "pages": pages_info}
204
-
205
- except Exception as e:
206
- return {"success": False, "error": str(e)}
207
-
208
-
209
- # Tool registration functions
210
- def register_initialize_browser(agent):
211
- """Register the browser initialization tool."""
212
-
213
- @agent.tool
214
- async def browser_initialize(
215
- context: RunContext,
216
- headless: bool = False,
217
- browser_type: str = "chromium",
218
- homepage: str = "https://www.google.com",
219
- ) -> Dict[str, Any]:
220
- """
221
- Initialize the browser with specified settings. Must be called before using other browser tools.
222
-
223
- Args:
224
- headless: Run browser in headless mode (no GUI)
225
- browser_type: Browser engine (chromium, firefox, webkit)
226
- homepage: Initial page to load
227
-
228
- Returns:
229
- Dict with initialization results
230
- """
231
- return await initialize_browser(headless, browser_type, homepage)
232
-
233
-
234
- def register_close_browser(agent):
235
- """Register the browser close tool."""
236
-
237
- @agent.tool
238
- async def browser_close(context: RunContext) -> Dict[str, Any]:
239
- """
240
- Close the browser and clean up all resources.
241
-
242
- Returns:
243
- Dict with close results
244
- """
245
- return await close_browser()
246
-
247
-
248
- def register_get_browser_status(agent):
249
- """Register the browser status tool."""
250
-
251
- @agent.tool
252
- async def browser_status(context: RunContext) -> Dict[str, Any]:
253
- """
254
- Get current browser status and information.
255
-
256
- Returns:
257
- Dict with browser status and metadata
258
- """
259
- return await get_browser_status()
260
-
261
-
262
- def register_create_new_page(agent):
263
- """Register the new page creation tool."""
264
-
265
- @agent.tool
266
- async def browser_new_page(
267
- context: RunContext,
268
- url: Optional[str] = None,
269
- ) -> Dict[str, Any]:
270
- """
271
- Create a new browser page/tab.
272
-
273
- Args:
274
- url: Optional URL to navigate to in the new page
275
-
276
- Returns:
277
- Dict with new page results
278
- """
279
- return await create_new_page(url)
280
-
281
-
282
- def register_list_pages(agent):
283
- """Register the list pages tool."""
284
-
285
- @agent.tool
286
- async def browser_list_pages(context: RunContext) -> Dict[str, Any]:
287
- """
288
- List all open browser pages/tabs.
289
-
290
- Returns:
291
- Dict with information about all open pages
292
- """
293
- return await list_pages()