1313from dendrite_sdk .async_api ._core .models .api_config import APIConfig
1414
1515
16+ CACHE_TIMEOUT = 5
17+
18+
1619class GetElementMixin (DendritePageProtocol ):
1720 @overload
1821 async def get_elements (
@@ -28,7 +31,9 @@ async def get_elements(
2831 Args:
2932 prompt_or_elements (str): The prompt describing the elements to be retrieved.
3033 use_cache (bool, optional): Whether to use cached results. Defaults to True.
31- timeout (int, optional): The total timeout (in milliseconds) until the last request is sent to the API. Defaults to 15000 (15 seconds).
34+ timeout (int, optional): Maximum time in milliseconds for the entire operation. If use_cache=True,
35+ up to 5000ms will be spent attempting to use cached selectors before falling back to the
36+ find element agent for the remaining time. Defaults to 15000 (15 seconds).
3237 context (str, optional): Additional context for the retrieval. Defaults to an empty string.
3338
3439 Returns:
@@ -49,7 +54,9 @@ async def get_elements(
4954 Args:
5055 prompt_or_elements (Dict[str, str]): A dictionary where keys are field names and values are prompts describing the elements to be retrieved.
5156 use_cache (bool, optional): Whether to use cached results. Defaults to True.
52- timeout (int, optional): The total timeout (in milliseconds) until the last request is sent to the API. Defaults to 3000.
57+ timeout (int, optional): Maximum time in milliseconds for the entire operation. If use_cache=True,
58+ up to 5000ms will be spent attempting to use cached selectors before falling back to the
59+ find element agent for the remaining time. Defaults to 15000 (15 seconds).
5360 context (str, optional): Additional context for the retrieval. Defaults to an empty string.
5461
5562 Returns:
@@ -72,7 +79,9 @@ async def get_elements(
7279 Args:
7380 prompt_or_elements (Union[str, Dict[str, str]]): The prompt or dictionary of prompts for element retrieval.
7481 use_cache (bool, optional): Whether to use cached results. Defaults to True.
75- timeout (int, optional): The total timeout (in milliseconds) until the last request is sent to the API. Defaults to 3000.
82+ timeout (int, optional): Maximum time in milliseconds for the entire operation. If use_cache=True,
83+ up to 5000ms will be spent attempting to use cached selectors before falling back to the
84+ find element agent for the remaining time. Defaults to 15000 (15 seconds).
7685 context (str, optional): Additional context for the retrieval. Defaults to an empty string.
7786
7887 Returns:
@@ -86,11 +95,9 @@ async def get_elements(
8695 prompt_or_elements ,
8796 only_one = False ,
8897 use_cache = use_cache ,
89- timeout = timeout ,
98+ timeout = timeout / 1000 ,
9099 )
91100
92- raise ValueError ("Prompt must be either a string prompt or a dictionary" )
93-
94101 async def get_element (
95102 self ,
96103 prompt : str ,
@@ -103,7 +110,9 @@ async def get_element(
103110 Args:
104111 prompt (str): The prompt describing the element to be retrieved.
105112 use_cache (bool, optional): Whether to use cached results. Defaults to True.
106- timeout (int, optional): The total timeout (in milliseconds) until the last request is sent to the API. Defaults to 15000 (15 seconds).
113+ timeout (int, optional): Maximum time in milliseconds for the entire operation. If use_cache=True,
114+ up to 5000ms will be spent attempting to use cached selectors before falling back to the
115+ find element agent for the remaining time. Defaults to 15000 (15 seconds).
107116
108117 Returns:
109118 AsyncElement: The retrieved element.
@@ -112,7 +121,7 @@ async def get_element(
112121 prompt ,
113122 only_one = True ,
114123 use_cache = use_cache ,
115- timeout = timeout ,
124+ timeout = timeout / 1000 ,
116125 )
117126
118127 @overload
@@ -130,7 +139,9 @@ async def _get_element(
130139 prompt (Union[str, Dict[str, str]]): The prompt describing the element to be retrieved.
131140 only_one (Literal[True]): Indicates that only one element should be retrieved.
132141 use_cache (bool): Whether to use cached results.
133- timeout: The total timeout (in milliseconds) until the last request is sent to the API.
142+ timeout (int, optional): Maximum time in milliseconds for the entire operation. If use_cache=True,
143+ up to 5000ms will be spent attempting to use cached selectors before falling back to the
144+ find element agent for the remaining time. Defaults to 15000 (15 seconds).
134145
135146 Returns:
136147 AsyncElement: The retrieved element.
@@ -151,7 +162,9 @@ async def _get_element(
151162 prompt (str): The prompt describing the elements to be retrieved.
152163 only_one (Literal[False]): Indicates that multiple elements should be retrieved.
153164 use_cache (bool): Whether to use cached results.
154- timeout: The total timeout (in milliseconds) until the last request is sent to the API.
165+ timeout (int, optional): Maximum time in milliseconds for the entire operation. If use_cache=True,
166+ up to 5000ms will be spent attempting to use cached selectors before falling back to the
167+ find element agent for the remaining time. Defaults to 15000 (15 seconds).
155168
156169 Returns:
157170 List[AsyncElement]: A list of retrieved elements.
@@ -177,7 +190,9 @@ async def _get_element(
177190 prompt_or_elements (Union[str, Dict[str, str]]): The prompt or dictionary of prompts for element retrieval.
178191 only_one (bool): Whether to retrieve only one element or a list of elements.
179192 use_cache (bool): Whether to use cached results.
180- timeout (float): The total timeout (in seconds) for the entire operation.
193+ timeout (int, optional): Maximum time in milliseconds for the entire operation. If use_cache=True,
194+ up to 5000ms will be spent attempting to use cached selectors before falling back to the
195+ find element agent for the remaining time. Defaults to 15000 (15 seconds).
181196
182197 Returns:
183198 Union[AsyncElement, List[AsyncElement], AsyncElementsResponse]: The retrieved element, list of elements, or response object.
@@ -187,7 +202,7 @@ async def _get_element(
187202 start_time = time .time ()
188203
189204 # First, let's check if there is a cached selector
190- cache_available = await test_if_cache_available (self ,prompt_or_elements )
205+ cache_available = await test_if_cache_available (self , prompt_or_elements )
191206
192207 # If we have cached elements, attempt to use them with an exponentation backoff
193208 if cache_available and use_cache == True :
@@ -197,8 +212,8 @@ async def _get_element(
197212 prompt_or_elements ,
198213 only_one ,
199214 api_config ,
215+ remaining_timeout = CACHE_TIMEOUT ,
200216 only_use_cache = True ,
201- remaining_timeout = timeout - (time .time () - start_time ),
202217 )
203218 if res :
204219 return res
@@ -216,8 +231,8 @@ async def _get_element(
216231 prompt_or_elements ,
217232 only_one ,
218233 api_config ,
219- only_use_cache = False ,
220234 remaining_timeout = timeout - (time .time () - start_time ),
235+ only_use_cache = False ,
221236 )
222237 if res :
223238 return res
@@ -227,6 +242,7 @@ async def _get_element(
227242 )
228243 return None
229244
245+
230246async def test_if_cache_available (
231247 obj : DendritePageProtocol ,
232248 prompt_or_elements : Union [str , Dict [str , str ]],
@@ -240,13 +256,14 @@ async def test_if_cache_available(
240256 cache_available = await obj ._get_browser_api_client ().check_selector_cache (dto )
241257 return cache_available .exists
242258
259+
243260async def attempt_with_backoff (
244261 obj : DendritePageProtocol ,
245262 prompt_or_elements : Union [str , Dict [str , str ]],
246263 only_one : bool ,
247264 api_config : APIConfig ,
265+ remaining_timeout : float ,
248266 only_use_cache : bool = False ,
249- remaining_timeout : float = 15.0 ,
250267) -> Union [Optional [AsyncElement ], List [AsyncElement ], AsyncElementsResponse ]:
251268 TIMEOUT_INTERVAL : List [float ] = [0.15 , 0.45 , 1.0 , 2.0 , 4.0 , 8.0 ]
252269 total_elapsed_time = 0
@@ -294,6 +311,7 @@ async def attempt_with_backoff(
294311 logger .error (f"All attempts failed after { total_elapsed_time :.2f} seconds" )
295312 return None
296313
314+
297315async def get_elements_from_selectors (
298316 obj : DendritePageProtocol , res : GetElementResponse , only_one : bool
299317) -> Union [Optional [AsyncElement ], List [AsyncElement ], AsyncElementsResponse ]:
@@ -302,9 +320,7 @@ async def get_elements_from_selectors(
302320 for key , selectors in res .selectors .items ():
303321 for selector in selectors :
304322 page = await obj ._get_page ()
305- dendrite_elements = await page ._get_all_elements_from_selector (
306- selector
307- )
323+ dendrite_elements = await page ._get_all_elements_from_selector (selector )
308324 if len (dendrite_elements ) > 0 :
309325 result [key ] = dendrite_elements [0 ]
310326 break
0 commit comments