dhisana 0.0.1.dev231__tar.gz → 0.0.1.dev233__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 (118) hide show
  1. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/PKG-INFO +1 -1
  2. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/setup.py +1 -1
  3. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/schemas/sales.py +4 -1
  4. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_email.py +60 -17
  5. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/test_connect.py +4 -3
  6. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana.egg-info/PKG-INFO +1 -1
  7. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/README.md +0 -0
  8. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/pyproject.toml +0 -0
  9. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/setup.cfg +0 -0
  10. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/__init__.py +0 -0
  11. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/cli/__init__.py +0 -0
  12. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/cli/cli.py +0 -0
  13. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/cli/datasets.py +0 -0
  14. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/cli/models.py +0 -0
  15. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/cli/predictions.py +0 -0
  16. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/schemas/__init__.py +0 -0
  17. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/schemas/common.py +0 -0
  18. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/ui/__init__.py +0 -0
  19. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/ui/components.py +0 -0
  20. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/__init__.py +0 -0
  21. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/add_mapping.py +0 -0
  22. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/agent_tools.py +0 -0
  23. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/apollo_tools.py +0 -0
  24. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/assistant_tool_tag.py +0 -0
  25. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/built_with_api_tools.py +0 -0
  26. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/cache_output_tools.py +0 -0
  27. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/cache_output_tools_local.py +0 -0
  28. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/check_email_validity_tools.py +0 -0
  29. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/check_for_intent_signal.py +0 -0
  30. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/check_linkedin_url_validity.py +0 -0
  31. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/clay_tools.py +0 -0
  32. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/clean_properties.py +0 -0
  33. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/company_utils.py +0 -0
  34. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/compose_salesnav_query.py +0 -0
  35. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/compose_search_query.py +0 -0
  36. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/compose_three_step_workflow.py +0 -0
  37. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/composite_tools.py +0 -0
  38. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/dataframe_tools.py +0 -0
  39. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/domain_parser.py +0 -0
  40. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/email_body_utils.py +0 -0
  41. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/email_parse_helpers.py +0 -0
  42. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/email_provider.py +0 -0
  43. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/enrich_lead_information.py +0 -0
  44. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/extract_email_content_for_llm.py +0 -0
  45. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/fetch_openai_config.py +0 -0
  46. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/field_validators.py +0 -0
  47. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/g2_tools.py +0 -0
  48. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_content.py +0 -0
  49. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_email_response.py +0 -0
  50. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_flow.py +0 -0
  51. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_leads_salesnav.py +0 -0
  52. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_linkedin_connect_message.py +0 -0
  53. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_linkedin_response_message.py +0 -0
  54. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/generate_structured_output_internal.py +0 -0
  55. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/google_custom_search.py +0 -0
  56. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/google_oauth_tools.py +0 -0
  57. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/google_workspace_tools.py +0 -0
  58. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/hubspot_clearbit.py +0 -0
  59. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/hubspot_crm_tools.py +0 -0
  60. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/instantly_tools.py +0 -0
  61. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/linkedin_crawler.py +0 -0
  62. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/lusha_tools.py +0 -0
  63. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/mailgun_tools.py +0 -0
  64. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/microsoft365_tools.py +0 -0
  65. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/openai_assistant_and_file_utils.py +0 -0
  66. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/openai_helpers.py +0 -0
  67. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/openapi_spec_to_tools.py +0 -0
  68. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/openapi_tool/__init__.py +0 -0
  69. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/openapi_tool/api_models.py +0 -0
  70. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/openapi_tool/convert_openai_spec_to_tool.py +0 -0
  71. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/openapi_tool/openapi_tool.py +0 -0
  72. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/parse_linkedin_messages_txt.py +0 -0
  73. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/profile.py +0 -0
  74. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/proxy_curl_tools.py +0 -0
  75. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/proxycurl_search_leads.py +0 -0
  76. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/python_function_to_tools.py +0 -0
  77. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/research_lead.py +0 -0
  78. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/sales_navigator_crawler.py +0 -0
  79. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/salesforce_crm_tools.py +0 -0
  80. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/search_router.py +0 -0
  81. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/search_router_jobs.py +0 -0
  82. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/sendgrid_tools.py +0 -0
  83. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serarch_router_local_business.py +0 -0
  84. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serpapi_additional_tools.py +0 -0
  85. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serpapi_google_jobs.py +0 -0
  86. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serpapi_google_search.py +0 -0
  87. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serpapi_local_business_search.py +0 -0
  88. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serpapi_search_tools.py +0 -0
  89. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serperdev_google_jobs.py +0 -0
  90. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serperdev_local_business.py +0 -0
  91. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/serperdev_search.py +0 -0
  92. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/smtp_email_tools.py +0 -0
  93. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/trasform_json.py +0 -0
  94. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/web_download_parse_tools.py +0 -0
  95. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/workflow_code_model.py +0 -0
  96. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/utils/zoominfo_tools.py +0 -0
  97. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/workflow/__init__.py +0 -0
  98. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/workflow/agent.py +0 -0
  99. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/workflow/flow.py +0 -0
  100. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/workflow/task.py +0 -0
  101. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana/workflow/test.py +0 -0
  102. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana.egg-info/SOURCES.txt +0 -0
  103. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana.egg-info/dependency_links.txt +0 -0
  104. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana.egg-info/entry_points.txt +0 -0
  105. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana.egg-info/requires.txt +0 -0
  106. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/src/dhisana.egg-info/top_level.txt +0 -0
  107. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_agent_tools.py +0 -0
  108. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_apollo_company_search.py +0 -0
  109. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_apollo_lead_search.py +0 -0
  110. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_connectivity.py +0 -0
  111. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_email_body_utils.py +0 -0
  112. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_google_document.py +0 -0
  113. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_hubspot_call_logs.py +0 -0
  114. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_linkedin_serper.py +0 -0
  115. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_mcp_connectivity.py +0 -0
  116. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_proxycurl_get_company_search_id.py +0 -0
  117. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/tests/test_proxycurl_job_count.py +0 -0
  118. {dhisana-0.0.1.dev231 → dhisana-0.0.1.dev233}/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.dev231
3
+ Version: 0.0.1.dev233
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-dev231',
5
+ version='0.0.1-dev233',
6
6
  description='A Python SDK for Dhisana AI Platform',
7
7
  author='Admin',
8
8
  author_email='contact@dhisana.ai',
@@ -291,10 +291,14 @@ class MessageGenerationInstructions(BaseModel):
291
291
  Holds the user-supplied instructions for generating the message:
292
292
  - instructions_to_generate_message: Plain text or template instructions from the user.
293
293
  - prompt_engineering_guidance: (Optional) Extra guidelines for structuring the prompt.
294
+ - allow_html: Whether HTML output is allowed.
295
+ - html_template: Optional HTML scaffolding or guidance.
294
296
  """
295
297
  instructions_to_generate_message: Optional[str] = None
296
298
  prompt_engineering_guidance: Optional[PromptEngineeringGuidance] = None
297
299
  use_cache: Optional[bool] = True
300
+ allow_html: Optional[bool] = False
301
+ html_template: Optional[str] = None
298
302
 
299
303
  class CampaignContext(BaseModel):
300
304
  """
@@ -938,4 +942,3 @@ class CompanyQueryFilters(BaseModel):
938
942
  default=None,
939
943
  description="Maximum founding year for the organization."
940
944
  )
941
-
@@ -1,4 +1,6 @@
1
1
  # Import necessary modules
2
+ import html as html_lib
3
+ import re
2
4
  from typing import Dict, List, Optional
3
5
  from pydantic import BaseModel
4
6
 
@@ -16,9 +18,22 @@ from pydantic import BaseModel, ConfigDict
16
18
  class EmailCopy(BaseModel):
17
19
  subject: str
18
20
  body: str
21
+ body_html: Optional[str] = None
19
22
 
20
23
  model_config = ConfigDict(extra="forbid")
21
24
 
25
+
26
+ def _html_to_plain_text(html_content: str) -> str:
27
+ """Simple HTML to text conversion to backfill plain body."""
28
+ if not html_content:
29
+ return ""
30
+ # Remove tags and normalize whitespace
31
+ text = re.sub(r"<[^>]+>", " ", html_content)
32
+ text = html_lib.unescape(text)
33
+ # Collapse repeated whitespace/newlines
34
+ lines = [line.strip() for line in text.splitlines()]
35
+ return "\n".join([line for line in lines if line])
36
+
22
37
  # -----------------------------------------------------------------------------
23
38
  # Utility to Clean Up Context (if needed)
24
39
  # -----------------------------------------------------------------------------
@@ -89,6 +104,42 @@ async def generate_personalized_email_copy(
89
104
  campaign_data = cleaned_context.campaign_context or CampaignContext()
90
105
  conversation_data = cleaned_context.current_conversation_context or ConversationContext()
91
106
 
107
+ html_note = (
108
+ f"\n Provide the HTML body using this guidance/template when possible:\n {message_instructions.html_template}"
109
+ if getattr(message_instructions, "html_template", None)
110
+ else ""
111
+ )
112
+ important_requirements = """
113
+ IMPORTANT REQUIREMENTS:
114
+ - Output must be JSON with "subject", "body", and "body_html" fields.
115
+ - "body_html" should be clean HTML suitable for email (no external assets), inline styles welcome.
116
+ - "body" must be the plain-text equivalent of "body_html".
117
+ - Keep it concise and relevant. No placeholders or extra instructions.
118
+ - Do not include PII or internal references, guids or content identifiers in the email.
119
+ - Use conversational names for company/person placeholders when provided.
120
+ - Email has salutation Hi <First Name>, unless otherwise specified.
121
+ - Make sure the signature in body has the sender_first_name correct and in the format the user specified.
122
+ - Do Not Make up information. use the information provided in the context and instructions only.
123
+ - Do Not use em dash in the generated output.
124
+ """
125
+ if not getattr(message_instructions, "allow_html", False):
126
+ important_requirements = """
127
+ IMPORTANT REQUIREMENTS:
128
+ - Output must be JSON with "subject" and "body" fields only.
129
+ - In the subject or body DO NOT include any HTML tags like <a>, <b>, <i>, etc.
130
+ - The body and subject should be in plain text.
131
+ - If there is a link provided in email use it as is. dont wrap it in any HTML tags.
132
+ - Keep it concise and relevant. No placeholders or extra instructions.
133
+ - Do not include PII or internal references, guids or content identifiers in the email.
134
+ - User conversational name for company name if used.
135
+ - Email has saluation Hi <First Name>, unless otherwise specified.
136
+ - <First Name> is the first name of the lead. Its conversational name. It does not have any special characters or spaces.
137
+ - Make sure the signature in body has the sender_first_name is correct and in the format user has specified.
138
+ - Do Not Make up information. use the information provided in the context and instructions only.
139
+ - Make sure the body text is well-formatted and that newline and carriage-return characters are correctly present and preserved in the message body.
140
+ - Do Not use em dash in the generated output.
141
+ """
142
+
92
143
  # Construct the consolidated prompt
93
144
  initial_prompt = f"""
94
145
  Hi AI Assistant,
@@ -114,7 +165,7 @@ async def generate_personalized_email_copy(
114
165
  Triage Guidelines (LinkedIn): {campaign_data.linkedin_triage_guidelines or ''}
115
166
 
116
167
  4) Messaging Instructions (template/framework):
117
- {selected_instructions}
168
+ {selected_instructions}{html_note}
118
169
 
119
170
  5) External Data / Vector Store:
120
171
  (I will be provided with file_search tool if present.)
@@ -123,21 +174,7 @@ async def generate_personalized_email_copy(
123
174
  Email Thread: {conversation_data.current_email_thread or ''}
124
175
  LinkedIn Thread: {conversation_data.current_linkedin_thread or ''}
125
176
 
126
- IMPORTANT REQUIREMENTS:
127
- - Output must be JSON with "subject" and "body" fields only.
128
- - In the subject or body DO NOT include any HTML tags like <a>, <b>, <i>, etc.
129
- - The body and subject should be in plain text.
130
- - If there is a link provided in email use it as is. dont wrap it in any HTML tags.
131
- - Keep it concise and relevant. No placeholders or extra instructions.
132
- - Do not include PII or internal references, guids or content identifiers in the email.
133
- - User conversational name for company name if used.
134
- - Email has saluation Hi <First Name>, unless otherwise specified.
135
- - <First Name> is the first name of the lead. Its conversational name. It does not have any special characters or spaces.
136
- - Make sure the signature in body has the sender_first_name is correct and in the format user has specified.
137
- - Do Not Make up information. use the information provided in the context and instructions only.
138
- - Make sure the body text is well-formatted and that newline and carriage-return characters are correctly present and preserved in the message body.
139
- - Do Not use em dash in the generated output.
140
-
177
+ {important_requirements}
141
178
  """
142
179
 
143
180
  # Check if a vector store is available
@@ -169,6 +206,11 @@ async def generate_personalized_email_copy(
169
206
 
170
207
  if initial_status != "SUCCESS":
171
208
  raise Exception("Error: Could not generate initial draft for the personalized email.")
209
+ plain_body = initial_response.body
210
+ html_body = getattr(initial_response, "body_html", None)
211
+ if not plain_body and html_body:
212
+ plain_body = _html_to_plain_text(html_body)
213
+
172
214
  response_item = MessageItem(
173
215
  message_id="", # or some real ID if you have it
174
216
  thread_id="",
@@ -178,7 +220,8 @@ async def generate_personalized_email_copy(
178
220
  receiver_email=email_context.lead_info.email or "",
179
221
  iso_datetime=datetime.utcnow().isoformat(),
180
222
  subject=initial_response.subject,
181
- body=initial_response.body
223
+ body=plain_body,
224
+ html_body=html_body if getattr(message_instructions, "allow_html", False) else None,
182
225
  )
183
226
  return response_item.model_dump()
184
227
 
@@ -1229,13 +1229,14 @@ async def test_firefliesai(api_key: str) -> Dict[str, Any]:
1229
1229
 
1230
1230
 
1231
1231
  async def test_firecrawl(api_key: str) -> Dict[str, Any]:
1232
- """Quick check for Firecrawl API key validity."""
1233
- url = "https://api.firecrawl.com/v1/scrape"
1232
+ """Quick check for Firecrawl API key validity (official v1 endpoint)."""
1233
+ url = "https://api.firecrawl.dev/v1/scrape"
1234
1234
  headers = {
1235
- "x-api-key": api_key,
1235
+ "Authorization": f"Bearer {api_key}", # per Firecrawl v1 docs
1236
1236
  "Content-Type": "application/json",
1237
1237
  }
1238
1238
  payload = {"url": "https://example.com"}
1239
+
1239
1240
  try:
1240
1241
  async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10)) as session:
1241
1242
  async with session.post(url, headers=headers, json=payload) as response:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhisana
3
- Version: 0.0.1.dev231
3
+ Version: 0.0.1.dev233
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