code-puppy 0.0.175__py3-none-any.whl → 0.0.177__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/agents/__init__.py +2 -2
- code_puppy/agents/agent_code_puppy.py +2 -1
- code_puppy/agents/agent_creator_agent.py +3 -2
- code_puppy/agents/agent_manager.py +5 -5
- code_puppy/agents/base_agent.py +60 -40
- code_puppy/command_line/command_handler.py +19 -10
- code_puppy/command_line/mcp/start_all_command.py +1 -1
- code_puppy/command_line/mcp/start_command.py +0 -1
- code_puppy/command_line/mcp/stop_all_command.py +1 -1
- code_puppy/command_line/mcp/stop_command.py +1 -0
- code_puppy/config.py +5 -3
- code_puppy/main.py +5 -2
- code_puppy/mcp_/examples/retry_example.py +4 -1
- code_puppy/messaging/spinner/console_spinner.py +1 -1
- code_puppy/model_factory.py +1 -1
- code_puppy/round_robin_model.py +2 -4
- code_puppy/tools/agent_tools.py +10 -8
- code_puppy/tools/browser/browser_screenshot.py +4 -3
- code_puppy/tools/browser/browser_scripts.py +0 -6
- code_puppy/tools/browser/browser_workflows.py +28 -20
- code_puppy/tools/browser/camoufox_manager.py +33 -48
- code_puppy/tools/browser/vqa_agent.py +0 -2
- code_puppy/tools/browser_scripts.py +0 -6
- code_puppy/tools/browser_workflows.py +28 -20
- code_puppy/tools/command_runner.py +1 -1
- code_puppy/tui/app.py +3 -13
- code_puppy/tui/components/chat_view.py +1 -0
- code_puppy/tui/screens/settings.py +3 -3
- {code_puppy-0.0.175.dist-info → code_puppy-0.0.177.dist-info}/METADATA +10 -10
- {code_puppy-0.0.175.dist-info → code_puppy-0.0.177.dist-info}/RECORD +34 -35
- code_puppy/tools/camoufox_manager.py +0 -150
- {code_puppy-0.0.175.data → code_puppy-0.0.177.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.175.dist-info → code_puppy-0.0.177.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.175.dist-info → code_puppy-0.0.177.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.175.dist-info → code_puppy-0.0.177.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
code_puppy/__init__.py,sha256=ehbM1-wMjNmOXk_DBhhJECFyBv2dRHwwo7ucjHeM68E,107
|
|
2
2
|
code_puppy/__main__.py,sha256=pDVssJOWP8A83iFkxMLY9YteHYat0EyWDQqMkKHpWp4,203
|
|
3
3
|
code_puppy/callbacks.py,sha256=6wYB6K_fGSCkKKEFaYOYkJT45WaV5W_NhUIzcvVH_nU,5060
|
|
4
|
-
code_puppy/config.py,sha256=
|
|
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=
|
|
7
|
-
code_puppy/model_factory.py,sha256=
|
|
6
|
+
code_puppy/main.py,sha256=c5nxJ6eRve9KFFTxVtioWJ393e6sxy7quld9TQpsH94,20519
|
|
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
|
|
10
|
-
code_puppy/round_robin_model.py,sha256=
|
|
10
|
+
code_puppy/round_robin_model.py,sha256=UEfw-Ix7GpNRWSxxuJtA-EE4_A46KXjMgFRciprfLmg,5634
|
|
11
11
|
code_puppy/status_display.py,sha256=F6eEAkGePDp4StM2BWj-uLLQTDGtJrf0IufzCeP1rRg,8336
|
|
12
12
|
code_puppy/summarization_agent.py,sha256=LnObgtLmM6N4z2553XXQlXAOf8R1BPSNmFSfXkjpivg,3211
|
|
13
13
|
code_puppy/tui_state.py,sha256=TT76XBVapKj6fKjFzz6oxCONeN_BZwcMILxxZcxu6-Y,1171
|
|
14
14
|
code_puppy/version_checker.py,sha256=bjLDmgGPrl7XnYwX1u13O8uFlsfikV90PK6nbA9Z9QU,1150
|
|
15
|
-
code_puppy/agents/__init__.py,sha256=
|
|
16
|
-
code_puppy/agents/agent_code_puppy.py,sha256=
|
|
17
|
-
code_puppy/agents/agent_creator_agent.py,sha256=
|
|
18
|
-
code_puppy/agents/agent_manager.py,sha256=
|
|
15
|
+
code_puppy/agents/__init__.py,sha256=PtPB7Z5MSwmUKipgt_qxvIuGggcuVaYwNbnp1UP4tPc,518
|
|
16
|
+
code_puppy/agents/agent_code_puppy.py,sha256=vk25J5YSjt30ItfML8KyQc5QR8QumBv5_U8RhqaXUz4,7973
|
|
17
|
+
code_puppy/agents/agent_creator_agent.py,sha256=IiwVirB6uoIeGOmtetut9eDv6o055ykND3V-fvyA8Lw,23042
|
|
18
|
+
code_puppy/agents/agent_manager.py,sha256=USzTbsGGZ9CH17LFeb6P6Im8RPY8qZUGKoH9EZZyU3k,11413
|
|
19
19
|
code_puppy/agents/agent_qa_kitten.py,sha256=5PeFFSwCFlTUvP6h5bGntx0xv5NmRwBiw0HnMqY8nLI,9107
|
|
20
|
-
code_puppy/agents/base_agent.py,sha256=
|
|
20
|
+
code_puppy/agents/base_agent.py,sha256=Ld9WTYPMr2uewivHmjBr99L6vlkR1F7jdlz6XG_ZBUQ,37155
|
|
21
21
|
code_puppy/agents/json_agent.py,sha256=y6AYE3Fx9LhmemcPzt46d7359MNnkGIjU83YBGNer2g,4533
|
|
22
22
|
code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
|
|
23
|
-
code_puppy/command_line/command_handler.py,sha256=
|
|
23
|
+
code_puppy/command_line/command_handler.py,sha256=JeJo6kc9-4B7S0_pbMp1LO7jtAT6XMXtSSnOShfoG-Y,27237
|
|
24
24
|
code_puppy/command_line/file_path_completion.py,sha256=gw8NpIxa6GOpczUJRyh7VNZwoXKKn-yvCqit7h2y6Gg,2931
|
|
25
25
|
code_puppy/command_line/load_context_completion.py,sha256=6eZxV6Bs-EFwZjN93V8ZDZUC-6RaWxvtZk-04Wtikyw,2240
|
|
26
26
|
code_puppy/command_line/model_picker_completion.py,sha256=vYNCZS1QWu6fxF__hTwpc7jwH7h_48wUxrnITawc83E,4140
|
|
@@ -38,11 +38,11 @@ code_puppy/command_line/mcp/logs_command.py,sha256=x_QsVGPpI5XY7RCZtiNFegc6R3csi
|
|
|
38
38
|
code_puppy/command_line/mcp/remove_command.py,sha256=MrWmXQ9jZTq1wrohFDO3ls0a1faTHCqRZocN-ynTzh8,2753
|
|
39
39
|
code_puppy/command_line/mcp/restart_command.py,sha256=-arZhayEVjTg3WErQKiBoFxbpbQcFlPXTzUI5o8AQLg,3254
|
|
40
40
|
code_puppy/command_line/mcp/search_command.py,sha256=k4CGiNJ1MKJ1_dPHd3wlwXo899nzizSUr7PsR0V9y4Y,4113
|
|
41
|
-
code_puppy/command_line/mcp/start_all_command.py,sha256=
|
|
42
|
-
code_puppy/command_line/mcp/start_command.py,sha256=
|
|
41
|
+
code_puppy/command_line/mcp/start_all_command.py,sha256=aipniBcS9rHg7urqayMVQXXouE4WwLH4CtHkP7QDK5I,4197
|
|
42
|
+
code_puppy/command_line/mcp/start_command.py,sha256=RwLXjxfUzemaU-CKjq5_mCjzKyWbVsIJBbo-dMUfLMs,3107
|
|
43
43
|
code_puppy/command_line/mcp/status_command.py,sha256=tQJrEDlN4DJ3n9jnKW-4kD0vL3TyUQbovb4V3nz-RsA,6640
|
|
44
|
-
code_puppy/command_line/mcp/stop_all_command.py,sha256=
|
|
45
|
-
code_puppy/command_line/mcp/stop_command.py,sha256=
|
|
44
|
+
code_puppy/command_line/mcp/stop_all_command.py,sha256=z7a9DAnTVsvuxnDSLyllejCDJv8-fdbc1a90sWC93y0,3618
|
|
45
|
+
code_puppy/command_line/mcp/stop_command.py,sha256=TG4mc5JrWh8gnABQbQ5dQkh8RyMgnp_C75tW2QxVSkc,2496
|
|
46
46
|
code_puppy/command_line/mcp/test_command.py,sha256=Pjod77DYRcA9WDZcxaCe6AUgpEXKJr42QRkxMhSjXhM,3689
|
|
47
47
|
code_puppy/command_line/mcp/utils.py,sha256=0Wt4ttYgSlVvtusYmBLKXSkjAjcsDiUxcZQAoFLUNnE,3625
|
|
48
48
|
code_puppy/command_line/mcp/wizard_utils.py,sha256=mWuE5epVgCxgGoj-VGwPO_XWVkkXjegXoIJpC9LC2TM,11075
|
|
@@ -62,27 +62,26 @@ code_puppy/mcp_/retry_manager.py,sha256=evVxbtrsHNyo8UoI7zpO-NVDegibn82RLlgN8VKe
|
|
|
62
62
|
code_puppy/mcp_/server_registry_catalog.py,sha256=5H9S2IQIF9OE__tfsXmj_T8qOXceoTHH0AxLh4kAbpw,38729
|
|
63
63
|
code_puppy/mcp_/status_tracker.py,sha256=uekxrzkzIWrv3OfSVgblaPuoGFcAh_dBYwCcaHZ_CrM,12183
|
|
64
64
|
code_puppy/mcp_/system_tools.py,sha256=7_oR8k0c8YjtCcYF9g7A946oAGuKOf_i-92aJH7VmlQ,7331
|
|
65
|
-
code_puppy/mcp_/examples/retry_example.py,sha256=
|
|
65
|
+
code_puppy/mcp_/examples/retry_example.py,sha256=Qi5K6cNmhc5-zncZa0F_dkJUEdZ6OIgt1xfG5PUxt3Q,7234
|
|
66
66
|
code_puppy/messaging/__init__.py,sha256=h2eZ7nJblKF71_dNUIBj3vL5RDw7WGy8nh6T_EYVrcA,1176
|
|
67
67
|
code_puppy/messaging/message_queue.py,sha256=A6_CVn55tA5cINrIML9N_fS6fGQP-n8gC8abnkwF034,12572
|
|
68
68
|
code_puppy/messaging/queue_console.py,sha256=hf32bKfAOdAaxYuARnmDuWhq4ET77xMWDvu5_T2JggY,10912
|
|
69
69
|
code_puppy/messaging/renderers.py,sha256=9VOpVmu7emyyg1CXgm17u4IzMNcLHvueBl7G14pLQho,16123
|
|
70
70
|
code_puppy/messaging/spinner/__init__.py,sha256=9mkXPYojafydBOAMh9ZUrB4X6uH5Iqz_-E-Obpd72ko,1365
|
|
71
|
-
code_puppy/messaging/spinner/console_spinner.py,sha256=
|
|
71
|
+
code_puppy/messaging/spinner/console_spinner.py,sha256=L-9oyuHrzxhlNR3nxcxWbbwVf2_ReOe1tqRbiIJOe3k,6932
|
|
72
72
|
code_puppy/messaging/spinner/spinner_base.py,sha256=474qMrTYpNfWcprFzmhaOJEOC-2rRHpTFCLsnl54bXA,1689
|
|
73
73
|
code_puppy/messaging/spinner/textual_spinner.py,sha256=Omx9A-FSPkxYDMYgBXgYMBQnK-DMlyqLOgkFVG8cmo4,3465
|
|
74
74
|
code_puppy/plugins/__init__.py,sha256=fksDqMUiXPJ5WNuMsYsVR8ulueQRCXPlvECEyicHPtQ,1312
|
|
75
75
|
code_puppy/tools/__init__.py,sha256=BVTZ85jLHgDANwOnUSOz3UDlp8VQDq4DoGF23BRlyWw,6032
|
|
76
|
-
code_puppy/tools/agent_tools.py,sha256=
|
|
76
|
+
code_puppy/tools/agent_tools.py,sha256=VMTKPfNUiK90ifyJUtEvUpOHmmifpWCxDKv7j6oTaxI,5620
|
|
77
77
|
code_puppy/tools/browser_control.py,sha256=6E_Kq63cErBk-iM9-03Cq8sTWWLh-Tk2kpdrB_rMmbg,8603
|
|
78
78
|
code_puppy/tools/browser_interactions.py,sha256=m-bVsAUbdrS-P1GbS0ChO2tMMg4tMIsDX34azn_Olzs,17070
|
|
79
79
|
code_puppy/tools/browser_locators.py,sha256=ZshjhYuV600vJqXUC23oNX89AZLMvY8rlvj-9oy7GMw,19574
|
|
80
80
|
code_puppy/tools/browser_navigation.py,sha256=Tj_fNcM3KGpkM2UTKcGQX8BpI373Sv7xZAJf-U7pO5M,7621
|
|
81
81
|
code_puppy/tools/browser_screenshot.py,sha256=QSwxS37G4LSo-Q9SBiuIofxWKnyInM90TY-_fiWQLrs,9222
|
|
82
|
-
code_puppy/tools/browser_scripts.py,sha256=
|
|
83
|
-
code_puppy/tools/browser_workflows.py,sha256=
|
|
84
|
-
code_puppy/tools/
|
|
85
|
-
code_puppy/tools/command_runner.py,sha256=5H4wK-v3UQ713_0JRefpAwyxGBWD9R5yLptR6BhZyIY,22417
|
|
82
|
+
code_puppy/tools/browser_scripts.py,sha256=MMO5KRjdrhuLOoJGoKGG1jm6UAqhFhUznz02aWqhMAE,15065
|
|
83
|
+
code_puppy/tools/browser_workflows.py,sha256=SJfiM2SgZr-qeeQJEivGzUNc51AlLIoqj9h1-mTvVsA,6593
|
|
84
|
+
code_puppy/tools/command_runner.py,sha256=SRhTACgKklHUm_ztbFHnefGbLw4CJOm601or6L1cPGM,22417
|
|
86
85
|
code_puppy/tools/common.py,sha256=pL-9xcRs3rxU7Fl9X9EUgbDp2-csh2LLJ5DHH_KAHKY,10596
|
|
87
86
|
code_puppy/tools/file_modifications.py,sha256=EaDWcv6gi8wAvpgyeJdKSKPWg9fTpZoEkxQiLCE6rn4,23218
|
|
88
87
|
code_puppy/tools/file_operations.py,sha256=3RX-eqhIukle3KA-QTEaiTMIefOWy_JhmPQaijEAt6U,32481
|
|
@@ -92,16 +91,16 @@ code_puppy/tools/browser/browser_control.py,sha256=6E_Kq63cErBk-iM9-03Cq8sTWWLh-
|
|
|
92
91
|
code_puppy/tools/browser/browser_interactions.py,sha256=m-bVsAUbdrS-P1GbS0ChO2tMMg4tMIsDX34azn_Olzs,17070
|
|
93
92
|
code_puppy/tools/browser/browser_locators.py,sha256=ZshjhYuV600vJqXUC23oNX89AZLMvY8rlvj-9oy7GMw,19574
|
|
94
93
|
code_puppy/tools/browser/browser_navigation.py,sha256=Tj_fNcM3KGpkM2UTKcGQX8BpI373Sv7xZAJf-U7pO5M,7621
|
|
95
|
-
code_puppy/tools/browser/browser_screenshot.py,sha256=
|
|
96
|
-
code_puppy/tools/browser/browser_scripts.py,sha256=
|
|
97
|
-
code_puppy/tools/browser/browser_workflows.py,sha256=
|
|
98
|
-
code_puppy/tools/browser/camoufox_manager.py,sha256=
|
|
99
|
-
code_puppy/tools/browser/vqa_agent.py,sha256=
|
|
94
|
+
code_puppy/tools/browser/browser_screenshot.py,sha256=YU4olUqxhqyK3_pBC0BtU6A7_EEtiRlh6saj93nkKAg,8258
|
|
95
|
+
code_puppy/tools/browser/browser_scripts.py,sha256=MMO5KRjdrhuLOoJGoKGG1jm6UAqhFhUznz02aWqhMAE,15065
|
|
96
|
+
code_puppy/tools/browser/browser_workflows.py,sha256=jplJ1T60W3G4-dhVJX-CXkm9sskUH_Qzp0Dj-oubvrE,6142
|
|
97
|
+
code_puppy/tools/browser/camoufox_manager.py,sha256=RYvLcs0iAoVNtpLjrrA1uu6a5k9tAdBbmhWFGSWjX_A,6106
|
|
98
|
+
code_puppy/tools/browser/vqa_agent.py,sha256=0GMDgJAK728rIuSQxAVytFSNagjo0LCjCUxBTm3w9Po,1952
|
|
100
99
|
code_puppy/tui/__init__.py,sha256=XesAxIn32zLPOmvpR2wIDxDAnnJr81a5pBJB4cZp1Xs,321
|
|
101
|
-
code_puppy/tui/app.py,sha256=
|
|
100
|
+
code_puppy/tui/app.py,sha256=f_8c9t9WF1twn4GCNNnmEgklSyUDC-9-d8_Lkosszjk,37911
|
|
102
101
|
code_puppy/tui/messages.py,sha256=zQoToWI0eWdT36NEsY6RdCFzcDfAmfvoPlHv8jiCbgo,720
|
|
103
102
|
code_puppy/tui/components/__init__.py,sha256=uj5pnk3s6SEN3SbFI0ZnzaA2KK1NNg8TfUj6U-Z732U,455
|
|
104
|
-
code_puppy/tui/components/chat_view.py,sha256=
|
|
103
|
+
code_puppy/tui/components/chat_view.py,sha256=Ff6uM6J0yENISNAOYroX7F-JL73_ajUUcP5IZSf2mng,19914
|
|
105
104
|
code_puppy/tui/components/command_history_modal.py,sha256=pUPEQvoCWa2iUnuMgNwO22y8eUbyw0HpcPH3wAosHvU,7097
|
|
106
105
|
code_puppy/tui/components/copy_button.py,sha256=E4-OJYk5YNzDf-E81NyiVGKsTRPrUX-RnQ8qFuVnabw,4375
|
|
107
106
|
code_puppy/tui/components/custom_widgets.py,sha256=qsVsPLh_oUjMWBznewH8Ya1BdGSiIwNiad2qkdfvCJk,2114
|
|
@@ -116,11 +115,11 @@ code_puppy/tui/models/enums.py,sha256=1ulsei95Gxy4r1sk-m-Sm5rdmejYCGRI-YtUwJmKFf
|
|
|
116
115
|
code_puppy/tui/screens/__init__.py,sha256=tJ00d0aYQ9kzOGHRChqy6cCQ6JUKKXBzLUTEbk_eA2Y,286
|
|
117
116
|
code_puppy/tui/screens/help.py,sha256=eJuPaOOCp7ZSUlecearqsuX6caxWv7NQszUh0tZJjBM,3232
|
|
118
117
|
code_puppy/tui/screens/mcp_install_wizard.py,sha256=vObpQwLbXjQsxmSg-WCasoev1usEi0pollKnL0SHu9U,27693
|
|
119
|
-
code_puppy/tui/screens/settings.py,sha256
|
|
118
|
+
code_puppy/tui/screens/settings.py,sha256=-WLldnKyWVKUYVPJcfOn1UU6eP9t8lLPUAVI317SOOM,10685
|
|
120
119
|
code_puppy/tui/screens/tools.py,sha256=3pr2Xkpa9Js6Yhf1A3_wQVRzFOui-KDB82LwrsdBtyk,1715
|
|
121
|
-
code_puppy-0.0.
|
|
122
|
-
code_puppy-0.0.
|
|
123
|
-
code_puppy-0.0.
|
|
124
|
-
code_puppy-0.0.
|
|
125
|
-
code_puppy-0.0.
|
|
126
|
-
code_puppy-0.0.
|
|
120
|
+
code_puppy-0.0.177.data/data/code_puppy/models.json,sha256=iXmLZGflnQcu2DRh4WUlgAhoXdvoxUc7KBhB8YxawXM,3088
|
|
121
|
+
code_puppy-0.0.177.dist-info/METADATA,sha256=vB7gqal8pk_r66WIRbKSAwFc3m8DybT0lAHaCiMaTrE,20079
|
|
122
|
+
code_puppy-0.0.177.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
123
|
+
code_puppy-0.0.177.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
|
|
124
|
+
code_puppy-0.0.177.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
125
|
+
code_puppy-0.0.177.dist-info/RECORD,,
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
"""Camoufox browser manager - privacy-focused Firefox automation."""
|
|
2
|
-
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
import camoufox
|
|
6
|
-
from playwright.async_api import Browser, BrowserContext, Page
|
|
7
|
-
|
|
8
|
-
from code_puppy.messaging import emit_info
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class CamoufoxManager:
|
|
12
|
-
"""Singleton browser manager for Camoufox (privacy-focused Firefox) automation."""
|
|
13
|
-
|
|
14
|
-
_instance: Optional["CamoufoxManager"] = None
|
|
15
|
-
_browser: Optional[Browser] = None
|
|
16
|
-
_context: Optional[BrowserContext] = None
|
|
17
|
-
_initialized: bool = False
|
|
18
|
-
|
|
19
|
-
def __new__(cls):
|
|
20
|
-
if cls._instance is None:
|
|
21
|
-
cls._instance = super().__new__(cls)
|
|
22
|
-
return cls._instance
|
|
23
|
-
|
|
24
|
-
def __init__(self):
|
|
25
|
-
# Only initialize once
|
|
26
|
-
if hasattr(self, "_init_done"):
|
|
27
|
-
return
|
|
28
|
-
self._init_done = True
|
|
29
|
-
|
|
30
|
-
self.headless = False
|
|
31
|
-
self.homepage = "https://www.google.com"
|
|
32
|
-
# Camoufox-specific settings
|
|
33
|
-
self.geoip = True # Enable GeoIP spoofing
|
|
34
|
-
self.block_webrtc = True # Block WebRTC for privacy
|
|
35
|
-
self.humanize = True # Add human-like behavior
|
|
36
|
-
|
|
37
|
-
@classmethod
|
|
38
|
-
def get_instance(cls) -> "CamoufoxManager":
|
|
39
|
-
"""Get the singleton instance."""
|
|
40
|
-
if cls._instance is None:
|
|
41
|
-
cls._instance = cls()
|
|
42
|
-
return cls._instance
|
|
43
|
-
|
|
44
|
-
async def async_initialize(self) -> None:
|
|
45
|
-
"""Initialize Camoufox browser."""
|
|
46
|
-
if self._initialized:
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
try:
|
|
50
|
-
emit_info("[yellow]Initializing Camoufox (privacy Firefox)...[/yellow]")
|
|
51
|
-
|
|
52
|
-
# Launch Camoufox with basic privacy settings
|
|
53
|
-
# Note: Many advanced features require additional packages or are handled internally
|
|
54
|
-
camoufox_instance = camoufox.AsyncCamoufox(
|
|
55
|
-
headless=self.headless,
|
|
56
|
-
# Only using well-supported basic options
|
|
57
|
-
block_webrtc=self.block_webrtc,
|
|
58
|
-
humanize=self.humanize,
|
|
59
|
-
# Let camoufox handle other privacy settings automatically
|
|
60
|
-
)
|
|
61
|
-
self._browser = await camoufox_instance.start()
|
|
62
|
-
|
|
63
|
-
# Create context (Camoufox handles most privacy settings automatically)
|
|
64
|
-
self._context = await self._browser.new_context(
|
|
65
|
-
viewport={"width": 1920, "height": 1080},
|
|
66
|
-
ignore_https_errors=True,
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
# Create initial page and navigate to homepage
|
|
70
|
-
page = await self._context.new_page()
|
|
71
|
-
await page.goto(self.homepage)
|
|
72
|
-
|
|
73
|
-
self._initialized = True
|
|
74
|
-
emit_info(
|
|
75
|
-
"[green]✅ Camoufox initialized successfully (privacy-focused Firefox)[/green]"
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
except Exception as e:
|
|
79
|
-
emit_info(f"[red]❌ Failed to initialize Camoufox: {e}[/red]")
|
|
80
|
-
await self._cleanup()
|
|
81
|
-
raise
|
|
82
|
-
|
|
83
|
-
async def get_current_page(self) -> Optional[Page]:
|
|
84
|
-
"""Get the currently active page."""
|
|
85
|
-
if not self._initialized or not self._context:
|
|
86
|
-
await self.async_initialize()
|
|
87
|
-
|
|
88
|
-
if self._context:
|
|
89
|
-
pages = self._context.pages
|
|
90
|
-
return pages[0] if pages else None
|
|
91
|
-
return None
|
|
92
|
-
|
|
93
|
-
async def new_page(self, url: Optional[str] = None) -> Page:
|
|
94
|
-
"""Create a new page and optionally navigate to URL."""
|
|
95
|
-
if not self._initialized:
|
|
96
|
-
await self.async_initialize()
|
|
97
|
-
|
|
98
|
-
page = await self._context.new_page()
|
|
99
|
-
if url:
|
|
100
|
-
await page.goto(url)
|
|
101
|
-
return page
|
|
102
|
-
|
|
103
|
-
async def close_page(self, page: Page) -> None:
|
|
104
|
-
"""Close a specific page."""
|
|
105
|
-
await page.close()
|
|
106
|
-
|
|
107
|
-
async def get_all_pages(self) -> list[Page]:
|
|
108
|
-
"""Get all open pages."""
|
|
109
|
-
if not self._context:
|
|
110
|
-
return []
|
|
111
|
-
return self._context.pages
|
|
112
|
-
|
|
113
|
-
async def _cleanup(self) -> None:
|
|
114
|
-
"""Clean up browser resources."""
|
|
115
|
-
try:
|
|
116
|
-
if self._context:
|
|
117
|
-
await self._context.close()
|
|
118
|
-
self._context = None
|
|
119
|
-
if self._browser:
|
|
120
|
-
await self._browser.close()
|
|
121
|
-
self._browser = None
|
|
122
|
-
self._initialized = False
|
|
123
|
-
except Exception as e:
|
|
124
|
-
emit_info(f"[yellow]Warning during cleanup: {e}[/yellow]")
|
|
125
|
-
|
|
126
|
-
async def close(self) -> None:
|
|
127
|
-
"""Close the browser and clean up resources."""
|
|
128
|
-
await self._cleanup()
|
|
129
|
-
emit_info("[yellow]Camoufox browser closed[/yellow]")
|
|
130
|
-
|
|
131
|
-
def __del__(self):
|
|
132
|
-
"""Ensure cleanup on object destruction."""
|
|
133
|
-
# Note: Can't use async in __del__, so this is just a fallback
|
|
134
|
-
if self._initialized:
|
|
135
|
-
import asyncio
|
|
136
|
-
|
|
137
|
-
try:
|
|
138
|
-
loop = asyncio.get_event_loop()
|
|
139
|
-
if loop.is_running():
|
|
140
|
-
loop.create_task(self._cleanup())
|
|
141
|
-
else:
|
|
142
|
-
loop.run_until_complete(self._cleanup())
|
|
143
|
-
except:
|
|
144
|
-
pass # Best effort cleanup
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
# Convenience function for getting the singleton instance
|
|
148
|
-
def get_camoufox_manager() -> CamoufoxManager:
|
|
149
|
-
"""Get the singleton CamoufoxManager instance."""
|
|
150
|
-
return CamoufoxManager.get_instance()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|