optexity-browser-use 0.9.5__py3-none-any.whl → 0.9.5.2__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.
- browser_use/browser/session.py +8 -8
- browser_use/dom/serializer/serializer.py +47 -11
- browser_use/dom/views.py +16 -1
- {optexity_browser_use-0.9.5.dist-info → optexity_browser_use-0.9.5.2.dist-info}/METADATA +1 -1
- {optexity_browser_use-0.9.5.dist-info → optexity_browser_use-0.9.5.2.dist-info}/RECORD +8 -8
- {optexity_browser_use-0.9.5.dist-info → optexity_browser_use-0.9.5.2.dist-info}/WHEEL +0 -0
- {optexity_browser_use-0.9.5.dist-info → optexity_browser_use-0.9.5.2.dist-info}/entry_points.txt +0 -0
- {optexity_browser_use-0.9.5.dist-info → optexity_browser_use-0.9.5.2.dist-info}/licenses/LICENSE +0 -0
browser_use/browser/session.py
CHANGED
|
@@ -1361,14 +1361,14 @@ class BrowserSession(BaseModel):
|
|
|
1361
1361
|
# SecurityWatchdog only handles security policy enforcement
|
|
1362
1362
|
self._security_watchdog.attach_to_session()
|
|
1363
1363
|
|
|
1364
|
-
# Initialize AboutBlankWatchdog (handles about:blank pages and DVD loading animation on first load)
|
|
1365
|
-
AboutBlankWatchdog.model_rebuild()
|
|
1366
|
-
self._aboutblank_watchdog = AboutBlankWatchdog(event_bus=self.event_bus, browser_session=self)
|
|
1367
|
-
# self.event_bus.on(BrowserStopEvent, self._aboutblank_watchdog.on_BrowserStopEvent)
|
|
1368
|
-
# self.event_bus.on(BrowserStoppedEvent, self._aboutblank_watchdog.on_BrowserStoppedEvent)
|
|
1369
|
-
# self.event_bus.on(TabCreatedEvent, self._aboutblank_watchdog.on_TabCreatedEvent)
|
|
1370
|
-
# self.event_bus.on(TabClosedEvent, self._aboutblank_watchdog.on_TabClosedEvent)
|
|
1371
|
-
self._aboutblank_watchdog.attach_to_session()
|
|
1364
|
+
# # Initialize AboutBlankWatchdog (handles about:blank pages and DVD loading animation on first load)
|
|
1365
|
+
# AboutBlankWatchdog.model_rebuild()
|
|
1366
|
+
# self._aboutblank_watchdog = AboutBlankWatchdog(event_bus=self.event_bus, browser_session=self)
|
|
1367
|
+
# # self.event_bus.on(BrowserStopEvent, self._aboutblank_watchdog.on_BrowserStopEvent)
|
|
1368
|
+
# # self.event_bus.on(BrowserStoppedEvent, self._aboutblank_watchdog.on_BrowserStoppedEvent)
|
|
1369
|
+
# # self.event_bus.on(TabCreatedEvent, self._aboutblank_watchdog.on_TabCreatedEvent)
|
|
1370
|
+
# # self.event_bus.on(TabClosedEvent, self._aboutblank_watchdog.on_TabClosedEvent)
|
|
1371
|
+
# self._aboutblank_watchdog.attach_to_session()
|
|
1372
1372
|
|
|
1373
1373
|
# Initialize PopupsWatchdog (handles accepting and dismissing JS dialogs, alerts, confirm, onbeforeunload, etc.)
|
|
1374
1374
|
PopupsWatchdog.model_rebuild()
|
|
@@ -792,19 +792,22 @@ class DOMTreeSerializer:
|
|
|
792
792
|
return False
|
|
793
793
|
|
|
794
794
|
@staticmethod
|
|
795
|
-
def serialize_tree(node: SimplifiedNode | None, include_attributes: list[str], depth: int = 0) -> str:
|
|
795
|
+
def serialize_tree(node: SimplifiedNode | None, include_attributes: list[str], depth: int = 0, remove_empty_nodes: bool = False) -> tuple[list[str], bool]:
|
|
796
796
|
"""Serialize the optimized tree to string format."""
|
|
797
797
|
if not node:
|
|
798
|
-
return
|
|
798
|
+
return [], False
|
|
799
|
+
|
|
800
|
+
is_empty_node = False
|
|
799
801
|
|
|
800
802
|
# Skip rendering excluded nodes, but process their children
|
|
801
803
|
if hasattr(node, 'excluded_by_parent') and node.excluded_by_parent:
|
|
802
804
|
formatted_text = []
|
|
803
805
|
for child in node.children:
|
|
804
|
-
|
|
806
|
+
child_formatted_text, child_is_interactive = DOMTreeSerializer.serialize_tree(child, include_attributes, depth, remove_empty_nodes)
|
|
807
|
+
child_text = '\n'.join(child_formatted_text)
|
|
805
808
|
if child_text:
|
|
806
809
|
formatted_text.append(child_text)
|
|
807
|
-
return
|
|
810
|
+
return formatted_text, node.is_interactive
|
|
808
811
|
|
|
809
812
|
formatted_text = []
|
|
810
813
|
depth_str = depth * '\t'
|
|
@@ -814,10 +817,11 @@ class DOMTreeSerializer:
|
|
|
814
817
|
# Skip displaying nodes marked as should_display=False
|
|
815
818
|
if not node.should_display:
|
|
816
819
|
for child in node.children:
|
|
817
|
-
|
|
820
|
+
child_formatted_text, child_is_interactive = DOMTreeSerializer.serialize_tree(child, include_attributes, depth, remove_empty_nodes)
|
|
821
|
+
child_text = '\n'.join(child_formatted_text)
|
|
818
822
|
if child_text:
|
|
819
823
|
formatted_text.append(child_text)
|
|
820
|
-
return
|
|
824
|
+
return formatted_text, node.is_interactive
|
|
821
825
|
|
|
822
826
|
# Special handling for SVG elements - show the tag but collapse children
|
|
823
827
|
if node.original_node.tag_name.lower() == 'svg':
|
|
@@ -843,7 +847,7 @@ class DOMTreeSerializer:
|
|
|
843
847
|
line += ' /> <!-- SVG content collapsed -->'
|
|
844
848
|
formatted_text.append(line)
|
|
845
849
|
# Don't process children for SVG
|
|
846
|
-
return
|
|
850
|
+
return formatted_text, node.is_interactive
|
|
847
851
|
|
|
848
852
|
# Add element if clickable, scrollable, or iframe
|
|
849
853
|
is_any_scrollable = node.original_node.is_actually_scrollable or node.original_node.is_scrollable
|
|
@@ -936,6 +940,14 @@ class DOMTreeSerializer:
|
|
|
936
940
|
scroll_info_text = node.original_node.get_scroll_info_text()
|
|
937
941
|
if scroll_info_text:
|
|
938
942
|
line += f' ({scroll_info_text})'
|
|
943
|
+
else:
|
|
944
|
+
'''
|
|
945
|
+
We mark the node as empty if it has no attributes. like <button />.
|
|
946
|
+
But if it has some attributes, we don't mark it as empty. Like <button class="btn btn-primary">Login</button>.
|
|
947
|
+
We also don't touch scroll stuff as I do not know about that.
|
|
948
|
+
'''
|
|
949
|
+
if not attributes_html_str:
|
|
950
|
+
is_empty_node = True
|
|
939
951
|
|
|
940
952
|
formatted_text.append(line)
|
|
941
953
|
|
|
@@ -950,7 +962,8 @@ class DOMTreeSerializer:
|
|
|
950
962
|
|
|
951
963
|
# Process shadow DOM children
|
|
952
964
|
for child in node.children:
|
|
953
|
-
|
|
965
|
+
child_formatted_text, child_is_interactive = DOMTreeSerializer.serialize_tree(child, include_attributes, next_depth, remove_empty_nodes)
|
|
966
|
+
child_text = '\n'.join(child_formatted_text)
|
|
954
967
|
if child_text:
|
|
955
968
|
formatted_text.append(child_text)
|
|
956
969
|
|
|
@@ -972,13 +985,36 @@ class DOMTreeSerializer:
|
|
|
972
985
|
|
|
973
986
|
# Process children (for non-shadow elements)
|
|
974
987
|
if node.original_node.node_type != NodeType.DOCUMENT_FRAGMENT_NODE:
|
|
988
|
+
child_texts: list[str] = []
|
|
989
|
+
child_is_interactives: list[bool] = []
|
|
975
990
|
for child in node.children:
|
|
976
|
-
|
|
991
|
+
child_formatted_text, child_is_interactive = DOMTreeSerializer.serialize_tree(child, include_attributes, next_depth, remove_empty_nodes)
|
|
992
|
+
child_text = '\n'.join(child_formatted_text)
|
|
993
|
+
if child_text!='':
|
|
994
|
+
child_texts.append(child_text)
|
|
995
|
+
child_is_interactives.append(child_is_interactive)
|
|
996
|
+
|
|
997
|
+
if remove_empty_nodes and is_empty_node and depth >= 0:
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
if len(child_texts) >= 1 and len(formatted_text) > 0:
|
|
1001
|
+
if all(child_is_interactives):
|
|
1002
|
+
formatted_text.pop()
|
|
1003
|
+
|
|
1004
|
+
'''
|
|
1005
|
+
bring all children one level up as this is the new level of child if they start with a tab
|
|
1006
|
+
'''
|
|
1007
|
+
if all([child_text.startswith('\t') for child_text in child_texts]):
|
|
1008
|
+
for i in range(len(child_texts)):
|
|
1009
|
+
temp = [a[1:] for a in child_texts[i].split("\n")]
|
|
1010
|
+
child_texts[i] = "\n".join(temp)
|
|
1011
|
+
|
|
1012
|
+
for child_text in child_texts:
|
|
977
1013
|
if child_text:
|
|
978
1014
|
formatted_text.append(child_text)
|
|
979
1015
|
|
|
980
|
-
return
|
|
981
|
-
|
|
1016
|
+
return formatted_text, node.is_interactive
|
|
1017
|
+
|
|
982
1018
|
@staticmethod
|
|
983
1019
|
def _build_attributes_string(node: EnhancedDOMTreeNode, include_attributes: list[str], text: str) -> str:
|
|
984
1020
|
"""Build the attributes string for an element."""
|
browser_use/dom/views.py
CHANGED
|
@@ -817,6 +817,7 @@ class SerializedDOMState:
|
|
|
817
817
|
def llm_representation(
|
|
818
818
|
self,
|
|
819
819
|
include_attributes: list[str] | None = None,
|
|
820
|
+
remove_empty_nodes: bool = False,
|
|
820
821
|
) -> str:
|
|
821
822
|
"""Kinda ugly, but leaving this as an internal method because include_attributes are a parameter on the agent, so we need to leave it as a 2 step process"""
|
|
822
823
|
from browser_use.dom.serializer.serializer import DOMTreeSerializer
|
|
@@ -826,7 +827,21 @@ class SerializedDOMState:
|
|
|
826
827
|
|
|
827
828
|
include_attributes = include_attributes or DEFAULT_INCLUDE_ATTRIBUTES
|
|
828
829
|
|
|
829
|
-
|
|
830
|
+
formatted_text, is_interactive = DOMTreeSerializer.serialize_tree(self._root, include_attributes, remove_empty_nodes=remove_empty_nodes)
|
|
831
|
+
final_text = '\n'.join(formatted_text)
|
|
832
|
+
if remove_empty_nodes:
|
|
833
|
+
'''
|
|
834
|
+
remove extra tabs from the beginning of the lines
|
|
835
|
+
'''
|
|
836
|
+
formatted_text = final_text.split('\n')
|
|
837
|
+
for i in range(1,len(formatted_text)):
|
|
838
|
+
prev_tabs = len(formatted_text[i-1]) - len(formatted_text[i-1].lstrip('\t'))
|
|
839
|
+
curr_tabs = len(formatted_text[i]) - len(formatted_text[i].lstrip('\t'))
|
|
840
|
+
while curr_tabs - prev_tabs>1:
|
|
841
|
+
formatted_text[i] = formatted_text[i][1:]
|
|
842
|
+
curr_tabs = len(formatted_text[i]) - len(formatted_text[i].lstrip('\t'))
|
|
843
|
+
final_text = '\n'.join(formatted_text)
|
|
844
|
+
return final_text
|
|
830
845
|
|
|
831
846
|
@observe_debug(ignore_input=True, ignore_output=True, name='eval_representation')
|
|
832
847
|
def eval_representation(
|
|
@@ -31,7 +31,7 @@ browser_use/browser/__init__.py,sha256=-MlstnQw2ulh9gNkl2o1FC_fXGwZWf-N-SVcycwia
|
|
|
31
31
|
browser_use/browser/events.py,sha256=zdevl6XV1URi1l2oyK25PYnECp_5TCQujp4SJAYKGB0,18086
|
|
32
32
|
browser_use/browser/profile.py,sha256=JpyLRupA31gQ52sBQUVoE-MkLEjl_0nruikZp0X31rI,47237
|
|
33
33
|
browser_use/browser/python_highlights.py,sha256=l27_46HDphCB566hmOaY5-wLLHtQouBua8sjS4eUJo4,18151
|
|
34
|
-
browser_use/browser/session.py,sha256
|
|
34
|
+
browser_use/browser/session.py,sha256=-NInTkAjPSo0MJNfxwqB1S-foWHTAeBZrhGGhN2tAPA,126131
|
|
35
35
|
browser_use/browser/session_manager.py,sha256=XKk7S1JgS_9FXBISqzecQV_KH3hfhan7yOAQnkvQRZY,15412
|
|
36
36
|
browser_use/browser/video_recorder.py,sha256=N0swIzPd-2e08WQZ3ei5h5tbH1PQlmD_eNTIDAKjNSk,5360
|
|
37
37
|
browser_use/browser/views.py,sha256=HwxjM1y8N3QRr3vW4xQVLWX6E9x0rbF7V72ST0rXgkQ,6317
|
|
@@ -64,7 +64,7 @@ browser_use/dom/enhanced_snapshot.py,sha256=HKpb49COP7i6E2xjSpw6troTcLO0L9Ge7lmM
|
|
|
64
64
|
browser_use/dom/markdown_extractor.py,sha256=D8YXBTYAVQ9xOU_wQn8y5iUzdI2h8ysQ_l4BJK6D0-8,6470
|
|
65
65
|
browser_use/dom/service.py,sha256=zNOMj9LfO7NWleHkrI73Z1LWfWOLZOWzA19YZVvJbPE,31575
|
|
66
66
|
browser_use/dom/utils.py,sha256=jv5MN3kPkXhRYnvcyNmuMBNWjBu6yJ6oxwA31FdsIEw,4284
|
|
67
|
-
browser_use/dom/views.py,sha256=
|
|
67
|
+
browser_use/dom/views.py,sha256=Y3dgAAOV4aYvgQo022vPdSltzGOrX4ODGhQNQ83PaAA,29298
|
|
68
68
|
browser_use/dom/playground/extraction.py,sha256=lXh5nSVW53UxnVvWlawDaI2xYWO6tTao-dK2JEuW32s,12558
|
|
69
69
|
browser_use/dom/playground/multi_act.py,sha256=H-bQ1-bRPEeL9VmjIIKo0I_NDygRAD18kLIEM36mTRk,734
|
|
70
70
|
browser_use/dom/serializer/clickable_elements.py,sha256=O-r0Ntyh-kBc86a_D7snw8VWLBuwQQaTBP8siU1yxPU,6564
|
|
@@ -72,7 +72,7 @@ browser_use/dom/serializer/code_use_serializer.py,sha256=KZPRBzGJ50Kb2hqUh4eykwZ
|
|
|
72
72
|
browser_use/dom/serializer/eval_serializer.py,sha256=TbRmZcKDiD2ImUM16LBjtet-d2-_6yVlZpnDyUiGG3g,15097
|
|
73
73
|
browser_use/dom/serializer/html_serializer.py,sha256=G2k9PyS1byraiBVmb-r0zRPU7zdDY_r_yaZg_gnOX1E,6032
|
|
74
74
|
browser_use/dom/serializer/paint_order.py,sha256=NCirHXEt5CjrBSh9UT41x0yeJ9o1xmkh81fUDmTud24,5542
|
|
75
|
-
browser_use/dom/serializer/serializer.py,sha256=
|
|
75
|
+
browser_use/dom/serializer/serializer.py,sha256=UHdcz6od2IW-mk93iWqeJnbfbF9fhxGuowBqpQ2noas,47663
|
|
76
76
|
browser_use/filesystem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
77
77
|
browser_use/filesystem/file_system.py,sha256=Gq3eCYXghsMcnZcrFeRdVWfgi6jUIzEbYXgXhZ0PdDE,19513
|
|
78
78
|
browser_use/integrations/gmail/__init__.py,sha256=zjQIPpFYRMdaBv87KQZ0-rsuq3eBzLk7RFhQYG7b33Q,1020
|
|
@@ -140,8 +140,8 @@ browser_use/tools/utils.py,sha256=xvKOaZW6Q83qo3QjeR31ZR6ed4_DfkrP7tZC_NOuLPo,29
|
|
|
140
140
|
browser_use/tools/views.py,sha256=Oxfd1k7ka_P-qq0tc7pxxNlmsQJi5rmbqngrleTHquI,2920
|
|
141
141
|
browser_use/tools/registry/service.py,sha256=aagu-WrnMv4t_3x0rY10qP4W0dL6OBxd7Z41_Ku9tiY,22696
|
|
142
142
|
browser_use/tools/registry/views.py,sha256=4r3qysEE5UMER-G7PtU1j6RlsbKbUu6-1eGMN6xRG9A,5743
|
|
143
|
-
optexity_browser_use-0.9.5.dist-info/METADATA,sha256
|
|
144
|
-
optexity_browser_use-0.9.5.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
145
|
-
optexity_browser_use-0.9.5.dist-info/entry_points.txt,sha256=NceUXLtKZs9AznxXL8P1rxVQVpF8jyk0x3SXZGhU1VE,87
|
|
146
|
-
optexity_browser_use-0.9.5.dist-info/licenses/LICENSE,sha256=E1xXZxsO6VdmmwWgygDMBvZFSW01Hi5zKDLG4nbaml4,1069
|
|
147
|
-
optexity_browser_use-0.9.5.dist-info/RECORD,,
|
|
143
|
+
optexity_browser_use-0.9.5.2.dist-info/METADATA,sha256=h9XtPkgrAMiNVQJ_hfTVaSdGhQ1jRIdAqi4QjB6Qj9c,11790
|
|
144
|
+
optexity_browser_use-0.9.5.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
145
|
+
optexity_browser_use-0.9.5.2.dist-info/entry_points.txt,sha256=NceUXLtKZs9AznxXL8P1rxVQVpF8jyk0x3SXZGhU1VE,87
|
|
146
|
+
optexity_browser_use-0.9.5.2.dist-info/licenses/LICENSE,sha256=E1xXZxsO6VdmmwWgygDMBvZFSW01Hi5zKDLG4nbaml4,1069
|
|
147
|
+
optexity_browser_use-0.9.5.2.dist-info/RECORD,,
|
|
File without changes
|
{optexity_browser_use-0.9.5.dist-info → optexity_browser_use-0.9.5.2.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{optexity_browser_use-0.9.5.dist-info → optexity_browser_use-0.9.5.2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|