dhisana 0.0.1.dev250__py3-none-any.whl → 0.0.1.dev251__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.
@@ -2,6 +2,7 @@ import os
2
2
  import hashlib
3
3
  import json
4
4
  import logging
5
+ from datetime import datetime, timezone
5
6
 
6
7
  from azure.storage.blob import BlobServiceClient
7
8
  from azure.core.exceptions import ResourceNotFoundError, AzureError
@@ -49,10 +50,11 @@ def cache_output(tool_name: str, key: str, value, ttl: int = None) -> bool:
49
50
  # Construct the blob name using a virtual folder for the tool name
50
51
  blob_name = f"{tool_name}/{key_hash}.json"
51
52
 
52
- # Prepare the cache data
53
+ # Prepare the cache data with timestamp for TTL expiration checking
53
54
  cache_data = {
54
55
  "value": value,
55
- "ttl": ttl
56
+ "ttl": ttl,
57
+ "cached_at": datetime.now(timezone.utc).isoformat()
56
58
  }
57
59
  data = json.dumps(cache_data)
58
60
 
@@ -88,6 +90,24 @@ def retrieve_output(tool_name: str, key: str):
88
90
  download_stream = blob_client.download_blob()
89
91
  content = download_stream.readall() # content is in bytes
90
92
  cache_data = json.loads(content.decode("utf-8"))
93
+
94
+ # Check if TTL has expired
95
+ ttl = cache_data.get("ttl")
96
+ cached_at = cache_data.get("cached_at")
97
+
98
+ if ttl is not None and cached_at is not None:
99
+ try:
100
+ cached_time = datetime.fromisoformat(cached_at)
101
+ now = datetime.now(timezone.utc)
102
+ elapsed_seconds = (now - cached_time).total_seconds()
103
+ if elapsed_seconds > ttl:
104
+ logger.info(f"Cache expired for blob '{blob_name}' (elapsed: {elapsed_seconds}s, ttl: {ttl}s)")
105
+ return None
106
+ except (ValueError, TypeError) as e:
107
+ logger.warning(f"Error parsing cached_at timestamp: {e}")
108
+ # If we can't parse the timestamp, treat as expired for safety
109
+ return None
110
+
91
111
  return cache_data.get("value")
92
112
  except ResourceNotFoundError:
93
113
  # Blob does not exist
@@ -16,6 +16,9 @@ from urllib.parse import urlparse, urlunparse
16
16
  logging.basicConfig(level=logging.INFO)
17
17
  logger = logging.getLogger(__name__)
18
18
 
19
+ # Cache TTL for Proxycurl responses: 14 days in seconds
20
+ PROXYCURL_CACHE_TTL = 14 * 24 * 60 * 60 # 1,209,600 seconds
21
+
19
22
 
20
23
  def get_proxycurl_access_token(tool_config: Optional[List[Dict]] = None) -> str:
21
24
  """
@@ -117,7 +120,7 @@ async def enrich_person_info_from_proxycurl(
117
120
  if response.status == 200:
118
121
  result = await response.json()
119
122
  if linkedin_url:
120
- cache_output("enrich_person_info_from_proxycurl", linkedin_url, result)
123
+ cache_output("enrich_person_info_from_proxycurl", linkedin_url, result, ttl=PROXYCURL_CACHE_TTL)
121
124
  logger.info("Successfully retrieved person info from Proxycurl.")
122
125
  return result
123
126
  elif response.status == 404:
@@ -195,14 +198,14 @@ async def lookup_person_in_proxy_curl_by_name(
195
198
  logger.debug(f"Received response status: {response.status}")
196
199
  if response.status == 200:
197
200
  result = await response.json()
198
- cache_output("lookup_person_in_proxycurl_by_name", key, result)
201
+ cache_output("lookup_person_in_proxycurl_by_name", key, result, ttl=PROXYCURL_CACHE_TTL)
199
202
  logger.info("Successfully retrieved person search info from Proxycurl.")
200
203
  return result
201
204
  elif response.status == 404:
202
205
  msg = "Person not found"
203
206
  logger.warning(msg)
204
207
  if key:
205
- cache_output("lookup_person_in_proxycurl_by_name", key, {'error': msg})
208
+ cache_output("lookup_person_in_proxycurl_by_name", key, {'error': msg}, ttl=PROXYCURL_CACHE_TTL)
206
209
  return {'error': msg}
207
210
  elif response.status == 429:
208
211
  msg = "Rate limit exceeded"
@@ -415,7 +418,7 @@ async def enrich_organization_info_from_proxycurl(
415
418
  if response.status == 200:
416
419
  result = await response.json()
417
420
  transformed_result = transform_company_data(result)
418
- cache_output("enrich_organization_info_from_proxycurl", cache_key, transformed_result)
421
+ cache_output("enrich_organization_info_from_proxycurl", cache_key, transformed_result, ttl=PROXYCURL_CACHE_TTL)
419
422
  logger.info("Successfully retrieved and transformed organization info from Proxycurl by LinkedIn URL.")
420
423
  return transformed_result
421
424
  elif response.status == 429:
@@ -429,7 +432,7 @@ async def enrich_organization_info_from_proxycurl(
429
432
  f"Proxycurl organization profile not found for LinkedIn URL {standardized_url}: {error_text}"
430
433
  )
431
434
  cache_output(
432
- "enrich_organization_info_from_proxycurl", cache_key, {}
435
+ "enrich_organization_info_from_proxycurl", cache_key, {}, ttl=PROXYCURL_CACHE_TTL
433
436
  )
434
437
  return {}
435
438
  else:
@@ -483,7 +486,7 @@ async def enrich_organization_info_from_proxycurl(
483
486
  if profile_response.status == 200:
484
487
  result = await profile_response.json()
485
488
  transformed_result = transform_company_data(result)
486
- cache_output("enrich_organization_info_from_proxycurl", domain_cache_key, transformed_result)
489
+ cache_output("enrich_organization_info_from_proxycurl", domain_cache_key, transformed_result, ttl=PROXYCURL_CACHE_TTL)
487
490
  logger.info("Successfully retrieved and transformed organization info from Proxycurl by domain.")
488
491
  return transformed_result
489
492
  elif profile_response.status == 429:
@@ -509,7 +512,7 @@ async def enrich_organization_info_from_proxycurl(
509
512
  elif response.status == 404:
510
513
  msg = "Item not found"
511
514
  logger.warning(msg)
512
- cache_output("enrich_organization_info_from_proxycurl", domain_cache_key, {})
515
+ cache_output("enrich_organization_info_from_proxycurl", domain_cache_key, {}, ttl=PROXYCURL_CACHE_TTL)
513
516
  return {}
514
517
  else:
515
518
  error_text = await response.text()
@@ -572,7 +575,7 @@ async def enrich_job_info_from_proxycurl(
572
575
  logger.debug(f"Received response status: {response.status}")
573
576
  if response.status == 200:
574
577
  result = await response.json()
575
- cache_output("enrich_job_info_from_proxycurl", job_url, result)
578
+ cache_output("enrich_job_info_from_proxycurl", job_url, result, ttl=PROXYCURL_CACHE_TTL)
576
579
  logger.info("Successfully retrieved job info from Proxycurl.")
577
580
  return result
578
581
  elif response.status == 429:
@@ -583,7 +586,7 @@ async def enrich_job_info_from_proxycurl(
583
586
  elif response.status == 404:
584
587
  msg = "Job not found"
585
588
  logger.warning(msg)
586
- cache_output("enrich_job_info_from_proxycurl", job_url, {'error': msg})
589
+ cache_output("enrich_job_info_from_proxycurl", job_url, {'error': msg}, ttl=PROXYCURL_CACHE_TTL)
587
590
  return {'error': msg}
588
591
  else:
589
592
  error_text = await response.text()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhisana
3
- Version: 0.0.1.dev250
3
+ Version: 0.0.1.dev251
4
4
  Summary: A Python SDK for Dhisana AI Platform
5
5
  Home-page: https://github.com/dhisana-ai/dhisana-python-sdk
6
6
  Author: Admin
@@ -15,7 +15,7 @@ dhisana/utils/agent_tools.py,sha256=pzBFvfhU4wfSB4zv1eiRzjmnteJnfhC5V32r_v1m38Y,
15
15
  dhisana/utils/apollo_tools.py,sha256=1b9FaL_3spQKUsOP1k8-kD1kcFxCkG4KJHoN71SjOkU,69796
16
16
  dhisana/utils/assistant_tool_tag.py,sha256=rYRl8ubLI7fUUIjg30XTefHBkFgRqNEVC12lF6U6Z-8,119
17
17
  dhisana/utils/built_with_api_tools.py,sha256=TFNGhnPb2vFdveVCpjiCvE1WKe_eK95UPpR0Ha5NgMQ,10260
18
- dhisana/utils/cache_output_tools.py,sha256=sSAruvUZn-WAJQ0lB9T1QjSmkm-_14AuxC9xKmcCQ0k,3428
18
+ dhisana/utils/cache_output_tools.py,sha256=q-d-WR_pkIUQyCJk8T-u9sfTy1TvvWoD2kJlZfqY-vA,4392
19
19
  dhisana/utils/cache_output_tools_local.py,sha256=okVIY54Xs5avTLu5Sv8neEPsPBce501m-6E_UhQkCAg,2447
20
20
  dhisana/utils/check_email_validity_tools.py,sha256=s2x1O3U97C4JcxIVuVh3sbgYTZzG7eGJCJT1s3NmApY,26609
21
21
  dhisana/utils/check_for_intent_signal.py,sha256=pC9k1_2fuUXBUxmikfxmoILlqhGMsJDVxrX0m73XQzA,4517
@@ -62,7 +62,7 @@ dhisana/utils/openai_helpers.py,sha256=ZK9S5-jcLCpiiD6XBLkCqYcNz-AGYmO9xh4e2H-FD
62
62
  dhisana/utils/openapi_spec_to_tools.py,sha256=oBLVq3WeDWvW9O02NCvY8bxQURQdKwHJHGcX8bC_b2I,1926
63
63
  dhisana/utils/parse_linkedin_messages_txt.py,sha256=g3N_ac70mAEuDDQ7Ott6mkOaBwI3ZvcsJD3R9RlYwPQ,3320
64
64
  dhisana/utils/profile.py,sha256=12IhefaLp3j74zzBzVRe50_KWqtWZ_cdzUKlYNy9T2Y,1192
65
- dhisana/utils/proxy_curl_tools.py,sha256=nHm3K_EHX8I-VGwONzCVPIA-OzbVMRXSA3VzmT_-uWk,52632
65
+ dhisana/utils/proxy_curl_tools.py,sha256=3i7Qpk0POME5OU5-lHQ6BlnOi88tIZl-Z0oMrphnCFQ,52975
66
66
  dhisana/utils/proxycurl_search_leads.py,sha256=6PlraPNYQ4fIDzTYnY-T2g_ip5fPkqHigbGoPD8ZosQ,16131
67
67
  dhisana/utils/python_function_to_tools.py,sha256=jypddM6WTlIQmRWnqAugYJXvaPYaXaMgWAZRYeeGlj4,2682
68
68
  dhisana/utils/research_lead.py,sha256=L6w2fK5in8z2xmWnXBjbkvTdrwPf8ZfvAXq3gb7-S6s,7009
@@ -95,8 +95,8 @@ dhisana/workflow/agent.py,sha256=esv7_i_XuMkV2j1nz_UlsHov_m6X5WZZiZm_tG4OBHU,565
95
95
  dhisana/workflow/flow.py,sha256=xWE3qQbM7j2B3FH8XnY3zOL_QXX4LbTW4ArndnEYJE0,1638
96
96
  dhisana/workflow/task.py,sha256=HlWz9mtrwLYByoSnePOemBUBrMEcj7KbgNjEE1oF5wo,1830
97
97
  dhisana/workflow/test.py,sha256=E7lRnXK0PguTNzyasHytLzTJdkqIPxG5_4qk4hMEeKc,3399
98
- dhisana-0.0.1.dev250.dist-info/METADATA,sha256=9bsRxPnqegnPfRGa6sOVugYzcUOSwK1JNSz3SUdzusk,1190
99
- dhisana-0.0.1.dev250.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
100
- dhisana-0.0.1.dev250.dist-info/entry_points.txt,sha256=jujxteZmNI9EkEaK-pOCoWuBujU8TCevdkfl9ZcKHek,49
101
- dhisana-0.0.1.dev250.dist-info/top_level.txt,sha256=NETTHt6YifG_P7XtRHbQiXZlgSFk9Qh9aR-ng1XTf4s,8
102
- dhisana-0.0.1.dev250.dist-info/RECORD,,
98
+ dhisana-0.0.1.dev251.dist-info/METADATA,sha256=LbbiZTFJYpwScudL5nQgt_Seem5CqgywicGKDcJkBYI,1190
99
+ dhisana-0.0.1.dev251.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
100
+ dhisana-0.0.1.dev251.dist-info/entry_points.txt,sha256=jujxteZmNI9EkEaK-pOCoWuBujU8TCevdkfl9ZcKHek,49
101
+ dhisana-0.0.1.dev251.dist-info/top_level.txt,sha256=NETTHt6YifG_P7XtRHbQiXZlgSFk9Qh9aR-ng1XTf4s,8
102
+ dhisana-0.0.1.dev251.dist-info/RECORD,,