dhisana 0.0.1.dev230__py3-none-any.whl → 0.0.1.dev232__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.
dhisana/schemas/sales.py CHANGED
@@ -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
 
@@ -724,7 +724,7 @@ async def find_organization_linkedin_url_with_google_search(
724
724
  return ""
725
725
 
726
726
  if use_strict_check:
727
- queries = [f'site:linkedin.com/company "{company_name}" {company_domain} -intitle:"jobs" ']
727
+ queries = [f'site:linkedin.com/company "{company_name}" {company_domain} ']
728
728
  else:
729
729
  if company_location:
730
730
  queries = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhisana
3
- Version: 0.0.1.dev230
3
+ Version: 0.0.1.dev232
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
@@ -6,7 +6,7 @@ dhisana/cli/models.py,sha256=IzUFZW_X32mL3fpM1_j4q8AF7v5nrxJcxBoqvG-TTgA,706
6
6
  dhisana/cli/predictions.py,sha256=VYgoLK1Ksv6MFImoYZqjQJkds7e5Hso65dHwbxTNNzE,646
7
7
  dhisana/schemas/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
8
8
  dhisana/schemas/common.py,sha256=SI6nldyfvZhNhfJwy2Qo1VJ7xwuAlg4QHYGLWPoVvZo,9287
9
- dhisana/schemas/sales.py,sha256=KUicIFC8uy4WLJegD6xIdOCUb63yGoqlDq-lALIrJKU,33395
9
+ dhisana/schemas/sales.py,sha256=k-ZTB-DaQbjvI882L6443H4gspWBFY-VrY2_1xlLn74,33587
10
10
  dhisana/ui/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
11
11
  dhisana/ui/components.py,sha256=4NXrAyl9tx2wWwoVYyABO-EOGnreGMvql1AkXWajIIo,14316
12
12
  dhisana/utils/__init__.py,sha256=jv2YF__bseklT3OWEzlqJ5qE24c4aWd5F4r0TTjOrWQ,65
@@ -38,7 +38,7 @@ dhisana/utils/fetch_openai_config.py,sha256=LjWdFuUeTNeAW106pb7DLXZNElos2PlmXRe6
38
38
  dhisana/utils/field_validators.py,sha256=BZgNCpBG264aRqNUu_J67c6zfr15zlAaIw2XRy8J7DY,11809
39
39
  dhisana/utils/g2_tools.py,sha256=a4vmBYCBvLae5CdpOhMN1oNlvO8v9J1B5Sd8T5PzuU8,3346
40
40
  dhisana/utils/generate_content.py,sha256=1ycqHhxuxXnsX_5CNp5M6zW40VsM6toYMCwJU9jf__4,2111
41
- dhisana/utils/generate_email.py,sha256=DZETpEuHhsfoH7ua9ylkC0d5P-SXRohFy5XVOZ19QF8,10796
41
+ dhisana/utils/generate_email.py,sha256=YUhrku9meo3ee5Ft2ybtLTUTAfUf4quPmJp9hmSkdzM,12895
42
42
  dhisana/utils/generate_email_response.py,sha256=3pggNoJKwZ0bAZ3aKaelw7Qip7AsySh16Qw_36Q0Mh4,21212
43
43
  dhisana/utils/generate_flow.py,sha256=QMn6bWo0nH0fBvy2Ebub1XfH5udnVAqsPsbIqCtQPXU,4728
44
44
  dhisana/utils/generate_leads_salesnav.py,sha256=AONP1KXDJdg95JQBmKx5PQXUD2BHctc-MZOMuRfuK9U,12156
@@ -74,7 +74,7 @@ dhisana/utils/serpapi_additional_tools.py,sha256=Xb1tc_oK-IjI9ZrEruYhFg8UJMLHQDa
74
74
  dhisana/utils/serpapi_google_jobs.py,sha256=HUJFZEW8UvYqsW0sWlEDXgI_IUomh5fTkzRJzEgsDGc,4509
75
75
  dhisana/utils/serpapi_google_search.py,sha256=B3sVq2OXdrYmPbH7cjQN4RFoek96qgKzXIayKXn0HLU,7318
76
76
  dhisana/utils/serpapi_local_business_search.py,sha256=vinmuXLaQ_0BpEdwnONZ2vLTq5xnRh6ICmPbnpckSN4,5775
77
- dhisana/utils/serpapi_search_tools.py,sha256=_lPnrGyqO6iYGtB714_FBKw6_2XSDQWz2TZnZBOfSCk,31738
77
+ dhisana/utils/serpapi_search_tools.py,sha256=xiiYi6Rd6Mqn94mjSKEs5nNZk1l2-PW_hTL4grvxUpI,31722
78
78
  dhisana/utils/serperdev_google_jobs.py,sha256=m5_2f_5y79FOFZz1A_go6m0hIUfbbAoZ0YTjUMO2BSI,4508
79
79
  dhisana/utils/serperdev_local_business.py,sha256=JoZfTg58Hojv61cyuwA2lcnPdLT1lawnWaBNrUYWnuQ,6447
80
80
  dhisana/utils/serperdev_search.py,sha256=_iBKIfHMq4gFv5StYz58eArriygoi1zW6VnLlux8vto,9363
@@ -93,8 +93,8 @@ dhisana/workflow/agent.py,sha256=esv7_i_XuMkV2j1nz_UlsHov_m6X5WZZiZm_tG4OBHU,565
93
93
  dhisana/workflow/flow.py,sha256=xWE3qQbM7j2B3FH8XnY3zOL_QXX4LbTW4ArndnEYJE0,1638
94
94
  dhisana/workflow/task.py,sha256=HlWz9mtrwLYByoSnePOemBUBrMEcj7KbgNjEE1oF5wo,1830
95
95
  dhisana/workflow/test.py,sha256=E7lRnXK0PguTNzyasHytLzTJdkqIPxG5_4qk4hMEeKc,3399
96
- dhisana-0.0.1.dev230.dist-info/METADATA,sha256=KUn2bPTMShD6jzxX9yp9Xzb0wlzlNbUiE4CkuOTfcbk,1190
97
- dhisana-0.0.1.dev230.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
98
- dhisana-0.0.1.dev230.dist-info/entry_points.txt,sha256=jujxteZmNI9EkEaK-pOCoWuBujU8TCevdkfl9ZcKHek,49
99
- dhisana-0.0.1.dev230.dist-info/top_level.txt,sha256=NETTHt6YifG_P7XtRHbQiXZlgSFk9Qh9aR-ng1XTf4s,8
100
- dhisana-0.0.1.dev230.dist-info/RECORD,,
96
+ dhisana-0.0.1.dev232.dist-info/METADATA,sha256=RceG6DFxX8ctp-wWTECxTC_saDy69bTzmnB1FdWyf_I,1190
97
+ dhisana-0.0.1.dev232.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
98
+ dhisana-0.0.1.dev232.dist-info/entry_points.txt,sha256=jujxteZmNI9EkEaK-pOCoWuBujU8TCevdkfl9ZcKHek,49
99
+ dhisana-0.0.1.dev232.dist-info/top_level.txt,sha256=NETTHt6YifG_P7XtRHbQiXZlgSFk9Qh9aR-ng1XTf4s,8
100
+ dhisana-0.0.1.dev232.dist-info/RECORD,,