dhisana 0.0.1.dev302__tar.gz → 0.0.1.dev304__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.
Files changed (124) hide show
  1. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/PKG-INFO +1 -1
  2. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/setup.py +1 -1
  3. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/enrich_lead_information.py +51 -3
  4. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_custom_message.py +2 -1
  5. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_email.py +14 -0
  6. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_email_response.py +2 -1
  7. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_linkedin_response_message.py +2 -1
  8. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serpapi_search_tools.py +10 -40
  9. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana.egg-info/PKG-INFO +1 -1
  10. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/README.md +0 -0
  11. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/pyproject.toml +0 -0
  12. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/setup.cfg +0 -0
  13. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/__init__.py +0 -0
  14. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/cli/__init__.py +0 -0
  15. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/cli/cli.py +0 -0
  16. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/cli/datasets.py +0 -0
  17. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/cli/models.py +0 -0
  18. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/cli/predictions.py +0 -0
  19. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/schemas/__init__.py +0 -0
  20. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/schemas/common.py +0 -0
  21. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/schemas/sales.py +0 -0
  22. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/ui/__init__.py +0 -0
  23. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/ui/components.py +0 -0
  24. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/__init__.py +0 -0
  25. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/add_mapping.py +0 -0
  26. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/agent_tools.py +0 -0
  27. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/apollo_tools.py +0 -0
  28. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/assistant_tool_tag.py +0 -0
  29. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/built_with_api_tools.py +0 -0
  30. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/cache_output_tools.py +0 -0
  31. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/cache_output_tools_local.py +0 -0
  32. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/check_email_validity_tools.py +0 -0
  33. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/check_for_intent_signal.py +0 -0
  34. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/check_linkedin_url_validity.py +0 -0
  35. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/clay_tools.py +0 -0
  36. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/clean_properties.py +0 -0
  37. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/company_utils.py +0 -0
  38. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/compose_salesnav_query.py +0 -0
  39. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/compose_search_query.py +0 -0
  40. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/compose_three_step_workflow.py +0 -0
  41. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/composite_tools.py +0 -0
  42. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/dataframe_tools.py +0 -0
  43. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/domain_parser.py +0 -0
  44. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/email_body_utils.py +0 -0
  45. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/email_parse_helpers.py +0 -0
  46. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/email_provider.py +0 -0
  47. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/extract_email_content_for_llm.py +0 -0
  48. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/fetch_openai_config.py +0 -0
  49. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/field_validators.py +0 -0
  50. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/g2_tools.py +0 -0
  51. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_content.py +0 -0
  52. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_flow.py +0 -0
  53. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_leads_salesnav.py +0 -0
  54. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_linkedin_connect_message.py +0 -0
  55. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/generate_structured_output_internal.py +0 -0
  56. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/google_custom_search.py +0 -0
  57. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/google_oauth_tools.py +0 -0
  58. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/google_workspace_tools.py +0 -0
  59. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/hubspot_clearbit.py +0 -0
  60. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/hubspot_crm_tools.py +0 -0
  61. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/instantly_tools.py +0 -0
  62. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/linkedin_crawler.py +0 -0
  63. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/lusha_tools.py +0 -0
  64. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/mailgun_tools.py +0 -0
  65. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/mailreach_tools.py +0 -0
  66. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/microsoft365_tools.py +0 -0
  67. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/openai_assistant_and_file_utils.py +0 -0
  68. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/openai_helpers.py +0 -0
  69. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/openapi_spec_to_tools.py +0 -0
  70. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/openapi_tool/__init__.py +0 -0
  71. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/openapi_tool/api_models.py +0 -0
  72. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/openapi_tool/convert_openai_spec_to_tool.py +0 -0
  73. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/openapi_tool/openapi_tool.py +0 -0
  74. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/parse_linkedin_messages_txt.py +0 -0
  75. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/profile.py +0 -0
  76. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/proxy_curl_tools.py +0 -0
  77. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/proxycurl_search_leads.py +0 -0
  78. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/python_function_to_tools.py +0 -0
  79. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/research_lead.py +0 -0
  80. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/sales_navigator_crawler.py +0 -0
  81. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/salesforce_crm_tools.py +0 -0
  82. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/search_router.py +0 -0
  83. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/search_router_jobs.py +0 -0
  84. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/sendgrid_tools.py +0 -0
  85. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serarch_router_local_business.py +0 -0
  86. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serpapi_additional_tools.py +0 -0
  87. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serpapi_google_jobs.py +0 -0
  88. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serpapi_google_search.py +0 -0
  89. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serpapi_local_business_search.py +0 -0
  90. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serperdev_google_jobs.py +0 -0
  91. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serperdev_local_business.py +0 -0
  92. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/serperdev_search.py +0 -0
  93. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/smtp_email_tools.py +0 -0
  94. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/test_connect.py +0 -0
  95. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/trasform_json.py +0 -0
  96. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/web_download_parse_tools.py +0 -0
  97. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/workflow_code_model.py +0 -0
  98. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/utils/zoominfo_tools.py +0 -0
  99. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/workflow/__init__.py +0 -0
  100. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/workflow/agent.py +0 -0
  101. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/workflow/flow.py +0 -0
  102. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/workflow/task.py +0 -0
  103. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana/workflow/test.py +0 -0
  104. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana.egg-info/SOURCES.txt +0 -0
  105. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana.egg-info/dependency_links.txt +0 -0
  106. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana.egg-info/entry_points.txt +0 -0
  107. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana.egg-info/requires.txt +0 -0
  108. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/src/dhisana.egg-info/top_level.txt +0 -0
  109. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_agent_tools.py +0 -0
  110. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_apollo_company_search.py +0 -0
  111. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_apollo_lead_search.py +0 -0
  112. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_connectivity.py +0 -0
  113. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_email_body_utils.py +0 -0
  114. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_generate_email.py +0 -0
  115. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_google_document.py +0 -0
  116. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_hubspot_call_logs.py +0 -0
  117. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_linkedin_serper.py +0 -0
  118. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_mailreach.py +0 -0
  119. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_mcp_connectivity.py +0 -0
  120. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_normalize_graph_datetime.py +0 -0
  121. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_proxycurl_get_company_search_id.py +0 -0
  122. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_proxycurl_job_count.py +0 -0
  123. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_reply_thread_fallback.py +0 -0
  124. {dhisana-0.0.1.dev302 → dhisana-0.0.1.dev304}/tests/test_structured_output_with_mcp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhisana
3
- Version: 0.0.1.dev302
3
+ Version: 0.0.1.dev304
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
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='dhisana',
5
- version='0.0.1-dev302',
5
+ version='0.0.1-dev304',
6
6
  description='A Python SDK for Dhisana AI Platform',
7
7
  author='Admin',
8
8
  author_email='contact@dhisana.ai',
@@ -658,9 +658,57 @@ async def enrich_user_info(
658
658
  tool_config=tool_config,
659
659
  )
660
660
  if found_linkedin_url:
661
- user_linkedin_url = found_linkedin_url
662
- input_properties["user_linkedin_url"] = user_linkedin_url
663
- if not user_linkedin_url and email:
661
+ should_use_url = True
662
+ if use_strict_check and org_domain:
663
+ try:
664
+ temp_props = {"user_linkedin_url": found_linkedin_url}
665
+ enriched = await enrich_with_provider(temp_props, tool_config)
666
+ enriched_domain = (enriched.get("primary_domain_of_organization") or "").strip().lower()
667
+ # If no domain returned but we have an organization LinkedIn URL,
668
+ # look up the org to get its domain
669
+ if not enriched_domain:
670
+ enriched_org_linkedin = (enriched.get("organization_linkedin_url") or "").strip()
671
+ if enriched_org_linkedin:
672
+ try:
673
+ org_info = await search_organization_by_linkedin_or_domain(
674
+ linkedin_url=enriched_org_linkedin,
675
+ tool_config=tool_config,
676
+ )
677
+ enriched_domain = (org_info.get("domain") or "").strip().lower()
678
+ except Exception:
679
+ logger.debug("Could not look up org domain from LinkedIn URL: %s", enriched_org_linkedin)
680
+ input_org_domain = org_domain.strip().lower()
681
+ if input_org_domain and enriched_domain and enriched_domain != input_org_domain:
682
+ logger.info(
683
+ "Skipping Google-found LinkedIn URL %s: enriched domain '%s' does not match input domain '%s'",
684
+ found_linkedin_url, enriched_domain, input_org_domain,
685
+ )
686
+ should_use_url = False
687
+ elif input_org_domain and not enriched_domain:
688
+ logger.info(
689
+ "Skipping Google-found LinkedIn URL %s: could not determine enriched org domain to verify against input domain '%s'",
690
+ found_linkedin_url, input_org_domain,
691
+ )
692
+ should_use_url = False
693
+ except Exception:
694
+ logger.debug("Could not verify LinkedIn URL domain via enrichment; proceeding with found URL.")
695
+ if should_use_url:
696
+ user_linkedin_url = found_linkedin_url
697
+ input_properties["user_linkedin_url"] = user_linkedin_url
698
+ # Skip email-based LinkedIn search if strict check is on and the email
699
+ # domain doesn't match the expected org domain (would waste API calls
700
+ # searching for a person at a different company).
701
+ skip_email_search = False
702
+ if use_strict_check and org_domain and email:
703
+ email_domain = email.split("@")[-1].strip().lower()
704
+ if email_domain and org_domain.strip().lower() != email_domain:
705
+ skip_email_search = True
706
+ logger.info(
707
+ "Skipping email-based LinkedIn search: email domain '%s' does not match org domain '%s'",
708
+ email_domain, org_domain,
709
+ )
710
+
711
+ if not user_linkedin_url and email and not skip_email_search:
664
712
  # If we have an email but no LinkedIn URL yet, try searching by email via Google
665
713
  email_lookup_result = await find_user_linkedin_url_by_email_google(
666
714
  email=email,
@@ -11,6 +11,7 @@ from dhisana.utils.generate_structured_output_internal import (
11
11
  )
12
12
  from datetime import datetime
13
13
  from pydantic import BaseModel, ConfigDict
14
+ from dhisana.utils.generate_email import _sanitize_lead_for_prompt
14
15
 
15
16
  # -----------------------------------------------------------------------------
16
17
  # Custom Message schema
@@ -140,7 +141,7 @@ async def generate_custom_message_copy(
140
141
  Below is the context in 6 main sections. Use it to craft a concise, professional message:
141
142
 
142
143
  1) Lead Information:
143
- {lead_data.dict()}
144
+ {_sanitize_lead_for_prompt(lead_data)}
144
145
 
145
146
  2) Sender Information:
146
147
  Full Name: {sender_data.sender_full_name or ''}
@@ -33,6 +33,14 @@ class EmailCopy(BaseModel):
33
33
  # Phone-number pattern used to redact lead phone numbers from the prompt
34
34
  _PHONE_RE = re.compile(r"(\+?\d[\d\-.\s()]{7,}\d)")
35
35
 
36
+ # Large blobs that should never be forwarded into the email-generation prompt
37
+ _FULL_EXPORT_EXCLUDED_ADDITIONAL = {
38
+ "pc_person_data",
39
+ "pc_company_data",
40
+ "apollo_person_data",
41
+ "apollo_company_data",
42
+ }
43
+
36
44
 
37
45
  def _sanitize_lead_for_prompt(lead: "Lead") -> str:
38
46
  """Return a clean JSON string of lead data suitable for an LLM prompt.
@@ -53,6 +61,12 @@ def _sanitize_lead_for_prompt(lead: "Lead") -> str:
53
61
  if data.get("research_summary"):
54
62
  data["research_summary"] = _PHONE_RE.sub("[redacted]", data["research_summary"])
55
63
 
64
+ # Strip bulky raw-export blobs from additional_properties
65
+ ap = data.get("additional_properties")
66
+ if isinstance(ap, dict):
67
+ for key in _FULL_EXPORT_EXCLUDED_ADDITIONAL:
68
+ ap.pop(key, None)
69
+
56
70
  return json.dumps(data, indent=2, default=str)
57
71
 
58
72
 
@@ -11,6 +11,7 @@ from dhisana.schemas.sales import (
11
11
  SenderInfo
12
12
  )
13
13
  from dhisana.utils.assistant_tool_tag import assistant_tool
14
+ from dhisana.utils.generate_email import _sanitize_lead_for_prompt
14
15
  from dhisana.utils.generate_structured_output_internal import (
15
16
  get_structured_output_with_assistant_and_vector_store,
16
17
  get_structured_output_internal
@@ -283,7 +284,7 @@ async def generate_inbound_email_response_copy(
283
284
  if cleaned_context.current_conversation_context.current_email_thread else []}
284
285
 
285
286
  2) Lead information:
286
- {lead_data.model_dump()}
287
+ {_sanitize_lead_for_prompt(lead_data)}
287
288
 
288
289
  Sender information:
289
290
  - Full name: {sender_data.sender_full_name or ''}
@@ -14,6 +14,7 @@ from dhisana.utils.generate_structured_output_internal import (
14
14
  get_structured_output_with_assistant_and_vector_store
15
15
  )
16
16
  from dhisana.utils.assistant_tool_tag import assistant_tool
17
+ from dhisana.utils.generate_email import _sanitize_lead_for_prompt
17
18
  import datetime
18
19
 
19
20
  # ---------------------------------------------------------------------------------------
@@ -112,7 +113,7 @@ async def generate_linkedin_response_message_copy(
112
113
 
113
114
  2.
114
115
  Lead Information:
115
- {lead_data.dict()}
116
+ {_sanitize_lead_for_prompt(lead_data)}
116
117
 
117
118
  Sender Information:
118
119
  Full Name: {sender_data.sender_full_name or ''}
@@ -401,12 +401,6 @@ async def find_user_linkedin_url_by_email_google(
401
401
  if query and query not in queries:
402
402
  queries.append(query)
403
403
 
404
- def add_query_parts(*parts: str) -> None:
405
- tokens = [part.strip() for part in parts if part and part.strip()]
406
- if not tokens:
407
- return
408
- add_query(" ".join(tokens))
409
-
410
404
  enriched_terms = []
411
405
  if user_name:
412
406
  enriched_terms.append(f'"{user_name}"')
@@ -418,47 +412,23 @@ async def find_user_linkedin_url_by_email_google(
418
412
  enriched_terms.append(f'"{user_location}"')
419
413
  base_hint = " ".join(enriched_terms)
420
414
 
421
- # Prioritise the direct email search variants before broader fallbacks.
422
- add_query_parts(normalized_email, "linkedin.com/in", base_hint)
423
- add_query_parts(normalized_email, "linkedin.com", base_hint)
424
- add_query_parts(normalized_email, "linkedin", base_hint)
425
- add_query_parts(normalized_email, base_hint)
426
- add_query(f'"{normalized_email}" "linkedin.com/in" {base_hint}')
427
- add_query(f'"{normalized_email}" "linkedin.com" {base_hint}')
428
- add_query(f'"{normalized_email}" linkedin {base_hint}')
415
+ # 1) Best query: site-scoped with exact email
416
+ add_query(f'site:linkedin.com/in "{normalized_email}" {base_hint}')
429
417
 
430
- if email_local_part and email_local_part != normalized_email:
431
- add_query_parts(email_local_part, "linkedin.com/in", base_hint)
432
- add_query_parts(email_local_part, "linkedin.com", base_hint)
433
- add_query_parts(email_local_part, "linkedin", base_hint)
434
- add_query(f'"{email_local_part}" "linkedin.com/in" {base_hint}')
435
- add_query(f'"{email_local_part}" "linkedin.com" {base_hint}')
418
+ # 2) Exact email with linkedin scope (Google may surface LinkedIn even without site:)
419
+ add_query(f'"{normalized_email}" linkedin.com/in {base_hint}')
436
420
 
437
- if email_local_humanized and email_local_humanized not in {email_local_part, normalized_email}:
438
- add_query_parts(email_local_humanized, "linkedin", base_hint)
439
- add_query(f'"{email_local_humanized}" linkedin {base_hint}')
421
+ # 3) Unquoted email with linkedin scope (catches partial matches)
422
+ add_query(f'{normalized_email} linkedin.com/in {base_hint}')
440
423
 
441
- if normalized_email:
442
- add_query(f'site:linkedin.com/in "{normalized_email}" {base_hint}')
443
-
444
- if email_local_part:
424
+ # 4) Local part fallback with site scope (e.g. "santosh" on linkedin)
425
+ if email_local_part and email_local_part != normalized_email:
445
426
  add_query(f'site:linkedin.com/in "{email_local_part}" {base_hint}')
446
427
 
447
- if email_local_humanized and email_local_humanized != email_local_part:
428
+ # 5) Humanized local part fallback (e.g. "john smith" from "john.smith")
429
+ if email_local_humanized and email_local_humanized not in {email_local_part, normalized_email}:
448
430
  add_query(f'site:linkedin.com/in "{email_local_humanized}" {base_hint}')
449
431
 
450
- if base_hint:
451
- lookup_hint = user_name or email_local_humanized or email_local_part or normalized_email
452
- add_query(
453
- f'site:linkedin.com/in "{normalized_email}" {base_hint} '
454
- f'intitle:"{lookup_hint}" -intitle:"profiles"'
455
- )
456
- if email_local_humanized:
457
- add_query(
458
- f'site:linkedin.com/in "{email_local_humanized}" {base_hint} '
459
- f'intitle:"{lookup_hint}" -intitle:"profiles"'
460
- )
461
-
462
432
  candidate_records: List[Dict[str, str]] = []
463
433
  seen_links: Set[str] = set()
464
434
  best_llm_choice: Optional[LinkedinCandidateChoice] = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhisana
3
- Version: 0.0.1.dev302
3
+ Version: 0.0.1.dev304
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
File without changes
File without changes