code-puppy 0.0.201__tar.gz → 0.0.203__tar.gz
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-0.0.201 → code_puppy-0.0.203}/PKG-INFO +2 -2
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_manager.py +4 -2
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/base_agent.py +2 -2
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/attachments.py +2 -14
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/camoufox_manager.py +52 -14
- {code_puppy-0.0.201 → code_puppy-0.0.203}/pyproject.toml +2 -2
- {code_puppy-0.0.201 → code_puppy-0.0.203}/.gitignore +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/LICENSE +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/README.md +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_c_reviewer.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_code_reviewer.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_cpp_reviewer.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_golang_reviewer.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_javascript_reviewer.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_python_reviewer.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_qa_expert.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_security_auditor.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/agent_typescript_reviewer.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/add_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/test_command.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/motd.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/config.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/main.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/messaging/spinner/textual_spinner.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/models.json +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/session_storage.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/browser/vqa_agent.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/app.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/chat_view.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/command_history_modal.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/copy_button.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/custom_widgets.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/human_input_modal.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/input_area.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/sidebar.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/status_bar.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/messages.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/models/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/models/chat_message.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/models/command_history.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/models/enums.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/screens/__init__.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/screens/autosave_picker.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/screens/help.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/screens/mcp_install_wizard.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/screens/settings.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/screens/tools.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui_state.py +0 -0
- {code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/version_checker.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: code-puppy
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.203
|
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.52
|
29
|
-
Requires-Dist: pydantic-ai==1.0.
|
29
|
+
Requires-Dist: pydantic-ai==1.0.5
|
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
|
@@ -252,7 +252,8 @@ def set_current_agent(agent_name: str) -> bool:
|
|
252
252
|
global _CURRENT_AGENT
|
253
253
|
curr_agent = get_current_agent()
|
254
254
|
if curr_agent is not None:
|
255
|
-
|
255
|
+
# Store a shallow copy so future mutations don't affect saved history
|
256
|
+
_AGENT_HISTORIES[curr_agent.name] = list(curr_agent.get_message_history())
|
256
257
|
# Generate a message group ID for agent switching
|
257
258
|
message_group_id = str(uuid.uuid4())
|
258
259
|
_discover_agents(message_group_id=message_group_id)
|
@@ -269,7 +270,8 @@ def set_current_agent(agent_name: str) -> bool:
|
|
269
270
|
_SESSION_AGENTS_CACHE[session_id] = agent_name
|
270
271
|
_save_session_data(_SESSION_AGENTS_CACHE)
|
271
272
|
if agent_obj.name in _AGENT_HISTORIES:
|
272
|
-
|
273
|
+
# Restore a copy to avoid sharing the same list instance
|
274
|
+
agent_obj.set_message_history(list(_AGENT_HISTORIES[agent_obj.name]))
|
273
275
|
on_agent_reload(agent_obj.id, agent_name)
|
274
276
|
return True
|
275
277
|
|
@@ -13,7 +13,7 @@ import pydantic
|
|
13
13
|
import pydantic_ai.models
|
14
14
|
from pydantic_ai import Agent as PydanticAgent
|
15
15
|
from pydantic_ai import BinaryContent, DocumentUrl, ImageUrl
|
16
|
-
from pydantic_ai import RunContext, UsageLimitExceeded
|
16
|
+
from pydantic_ai import RunContext, UsageLimitExceeded, UsageLimits
|
17
17
|
from pydantic_ai.messages import (
|
18
18
|
ModelMessage,
|
19
19
|
ModelRequest,
|
@@ -950,7 +950,7 @@ class BaseAgent(ABC):
|
|
950
950
|
self.set_message_history(
|
951
951
|
self.prune_interrupted_tool_calls(self.get_message_history())
|
952
952
|
)
|
953
|
-
usage_limits =
|
953
|
+
usage_limits = UsageLimits(request_limit=get_message_limit())
|
954
954
|
result_ = await pydantic_agent.run(
|
955
955
|
prompt_payload,
|
956
956
|
message_history=self.get_message_history(),
|
@@ -151,20 +151,8 @@ def _is_supported_extension(path: Path) -> bool:
|
|
151
151
|
|
152
152
|
|
153
153
|
def _parse_link(token: str) -> PromptLinkAttachment | None:
|
154
|
-
|
155
|
-
|
156
|
-
scheme = token.split(":", 1)[0].lower()
|
157
|
-
if scheme not in SUPPORTED_INLINE_SCHEMES:
|
158
|
-
return None
|
159
|
-
if token.lower().endswith(".pdf"):
|
160
|
-
return PromptLinkAttachment(
|
161
|
-
placeholder=token,
|
162
|
-
url_part=DocumentUrl(url=token),
|
163
|
-
)
|
164
|
-
return PromptLinkAttachment(
|
165
|
-
placeholder=token,
|
166
|
-
url_part=ImageUrl(url=token),
|
167
|
-
)
|
154
|
+
"""URL parsing disabled: no URLs are treated as attachments."""
|
155
|
+
return None
|
168
156
|
|
169
157
|
|
170
158
|
@dataclass
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""Camoufox browser manager - privacy-focused Firefox automation."""
|
2
2
|
|
3
|
-
from
|
3
|
+
from pathlib import Path
|
4
|
+
from typing import Optional, TypeAlias
|
4
5
|
|
5
6
|
import camoufox
|
6
7
|
from camoufox.addons import DefaultAddons
|
@@ -9,6 +10,8 @@ from camoufox.locale import ALLOW_GEOIP, download_mmdb
|
|
9
10
|
from camoufox.pkgman import CamoufoxFetcher, camoufox_path
|
10
11
|
from playwright.async_api import Browser, BrowserContext, Page
|
11
12
|
|
13
|
+
_MIN_VIEWPORT_DIMENSION = 640
|
14
|
+
|
12
15
|
from code_puppy.messaging import emit_info
|
13
16
|
|
14
17
|
|
@@ -38,6 +41,9 @@ class CamoufoxManager:
|
|
38
41
|
self.block_webrtc = True # Block WebRTC for privacy
|
39
42
|
self.humanize = True # Add human-like behavior
|
40
43
|
|
44
|
+
# Persistent profile directory for consistent browser state across runs
|
45
|
+
self.profile_dir = self._get_profile_directory()
|
46
|
+
|
41
47
|
@classmethod
|
42
48
|
def get_instance(cls) -> "CamoufoxManager":
|
43
49
|
"""Get the singleton instance."""
|
@@ -45,6 +51,16 @@ class CamoufoxManager:
|
|
45
51
|
cls._instance = cls()
|
46
52
|
return cls._instance
|
47
53
|
|
54
|
+
def _get_profile_directory(self) -> Path:
|
55
|
+
"""Get or create the persistent profile directory.
|
56
|
+
|
57
|
+
Returns a Path object pointing to ~/.code_puppy/camoufox_profile
|
58
|
+
where browser data (cookies, history, bookmarks, etc.) will be stored.
|
59
|
+
"""
|
60
|
+
profile_path = Path.home() / ".code_puppy" / "camoufox_profile"
|
61
|
+
profile_path.mkdir(parents=True, exist_ok=True)
|
62
|
+
return profile_path
|
63
|
+
|
48
64
|
async def async_initialize(self) -> None:
|
49
65
|
"""Initialize Camoufox browser."""
|
50
66
|
if self._initialized:
|
@@ -68,30 +84,40 @@ class CamoufoxManager:
|
|
68
84
|
|
69
85
|
async def _initialize_camoufox(self) -> None:
|
70
86
|
"""Try to start Camoufox with the configured privacy settings."""
|
87
|
+
emit_info(f"[cyan]📁 Using persistent profile: {self.profile_dir}[/cyan]")
|
88
|
+
|
71
89
|
camoufox_instance = camoufox.AsyncCamoufox(
|
72
90
|
headless=self.headless,
|
73
91
|
block_webrtc=self.block_webrtc,
|
74
92
|
humanize=self.humanize,
|
75
93
|
exclude_addons=list(DefaultAddons),
|
94
|
+
persistent_context=True,
|
95
|
+
user_data_dir=str(self.profile_dir),
|
76
96
|
addons=[],
|
77
97
|
)
|
78
|
-
|
79
|
-
self.
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
98
|
+
|
99
|
+
self._browser = camoufox_instance.browser
|
100
|
+
# Use persistent storage directory for browser context
|
101
|
+
# This ensures cookies, localStorage, history, etc. persist across runs
|
102
|
+
if not self._initialized:
|
103
|
+
self._context = await camoufox_instance.start()
|
104
|
+
self._initialized = True
|
105
|
+
# Do not auto-open a page here to avoid duplicate windows/tabs.
|
85
106
|
|
86
107
|
async def get_current_page(self) -> Optional[Page]:
|
87
|
-
"""Get the currently active page."""
|
108
|
+
"""Get the currently active page. Lazily creates one if none exist."""
|
88
109
|
if not self._initialized or not self._context:
|
89
110
|
await self.async_initialize()
|
90
111
|
|
91
|
-
if self._context:
|
92
|
-
|
93
|
-
|
94
|
-
|
112
|
+
if not self._context:
|
113
|
+
return None
|
114
|
+
|
115
|
+
pages = self._context.pages
|
116
|
+
if pages:
|
117
|
+
return pages[0]
|
118
|
+
|
119
|
+
# Lazily create a new blank page without navigation
|
120
|
+
return await self._context.new_page()
|
95
121
|
|
96
122
|
async def new_page(self, url: Optional[str] = None) -> Page:
|
97
123
|
"""Create a new page and optionally navigate to URL."""
|
@@ -140,9 +166,21 @@ class CamoufoxManager:
|
|
140
166
|
return self._context.pages
|
141
167
|
|
142
168
|
async def _cleanup(self) -> None:
|
143
|
-
"""Clean up browser resources."""
|
169
|
+
"""Clean up browser resources and save persistent state."""
|
144
170
|
try:
|
171
|
+
# Save browser state before closing (cookies, localStorage, etc.)
|
145
172
|
if self._context:
|
173
|
+
try:
|
174
|
+
storage_state_path = self.profile_dir / "storage_state.json"
|
175
|
+
await self._context.storage_state(path=str(storage_state_path))
|
176
|
+
emit_info(
|
177
|
+
f"[green]💾 Browser state saved to {storage_state_path}[/green]"
|
178
|
+
)
|
179
|
+
except Exception as e:
|
180
|
+
emit_info(
|
181
|
+
f"[yellow]Warning: Could not save storage state: {e}[/yellow]"
|
182
|
+
)
|
183
|
+
|
146
184
|
await self._context.close()
|
147
185
|
self._context = None
|
148
186
|
if self._browser:
|
@@ -4,12 +4,12 @@ build-backend = "hatchling.build"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "code-puppy"
|
7
|
-
version = "0.0.
|
7
|
+
version = "0.0.203"
|
8
8
|
description = "Code generation agent"
|
9
9
|
readme = "README.md"
|
10
10
|
requires-python = ">=3.11"
|
11
11
|
dependencies = [
|
12
|
-
"pydantic-ai==1.0.
|
12
|
+
"pydantic-ai==1.0.5",
|
13
13
|
"httpx>=0.24.1",
|
14
14
|
"rich>=13.4.2",
|
15
15
|
"logfire>=0.7.1",
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/load_context_completion.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/model_picker_completion.py
RENAMED
File without changes
|
File without changes
|
{code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/command_line/prompt_toolkit_completion.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{code_puppy-0.0.201 → code_puppy-0.0.203}/code_puppy/tui/components/command_history_modal.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|