dhisana 0.0.1.dev101__tar.gz → 0.0.1.dev102__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.
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/PKG-INFO +1 -1
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/setup.py +1 -1
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/apollo_tools.py +11 -1
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/check_email_validity_tools.py +17 -1
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/research_lead.py +32 -7
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana.egg-info/PKG-INFO +1 -1
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/README.md +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/pyproject.toml +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/setup.cfg +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/__init__.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/cli/__init__.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/cli/cli.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/cli/datasets.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/cli/models.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/cli/predictions.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/schemas/__init__.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/schemas/common.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/schemas/sales.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/ui/__init__.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/ui/components.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/__init__.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/add_mapping.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/agent_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/assistant_tool_tag.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/built_with_api_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/cache_output_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/cache_output_tools_local.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/check_for_intent_signal.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/check_linkedin_url_validity.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/clay_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/clean_properties.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/company_utils.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/compose_salesnav_query.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/compose_search_query.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/compose_three_step_workflow.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/composite_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/dataframe_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/domain_parser.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/email_parse_helpers.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/enrich_lead_information.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/extract_email_content_for_llm.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/field_validators.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/g2_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_content.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_email.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_email_response.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_flow.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_leads_salesnav.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_linkedin_connect_message.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_linkedin_response_message.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_structured_output_internal.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/google_custom_search.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/google_workspace_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/hubspot_clearbit.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/hubspot_crm_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/instantly_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/linkedin_crawler.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/lusha_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openai_assistant_and_file_utils.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openai_helpers.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openapi_spec_to_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openapi_tool/__init__.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openapi_tool/api_models.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openapi_tool/convert_openai_spec_to_tool.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openapi_tool/openapi_tool.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/parse_linkedin_messages_txt.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/proxy_curl_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/python_function_to_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/sales_navigator_crawler.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/salesforce_crm_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/sendgrid_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/serpapi_search_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/test_connect.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/trasform_json.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/web_download_parse_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/workflow_code_model.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/zoominfo_tools.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/workflow/__init__.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/workflow/agent.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/workflow/flow.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/workflow/task.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/workflow/test.py +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana.egg-info/SOURCES.txt +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana.egg-info/dependency_links.txt +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana.egg-info/entry_points.txt +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana.egg-info/requires.txt +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana.egg-info/top_level.txt +0 -0
- {dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/tests/test_agent_tools.py +0 -0
|
@@ -192,6 +192,16 @@ async def lookup_person_in_apollo_by_name(
|
|
|
192
192
|
"per_page": 10
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
# Build a cache key that includes full_name and company_name (if provided)
|
|
196
|
+
# so that results are correctly cached and retrieved.
|
|
197
|
+
key_item = f"lookup_person_in_apollo_by_name_{full_name}_{company_name or ''}".lower()
|
|
198
|
+
|
|
199
|
+
# Attempt to retrieve a cached response first
|
|
200
|
+
cached_response = retrieve_output("lookup_person_in_apollo_by_name", key_item)
|
|
201
|
+
if cached_response is not None:
|
|
202
|
+
logger.info(f"Cache hit for user: {full_name}, company: {company_name or ''}")
|
|
203
|
+
return cached_response
|
|
204
|
+
|
|
195
205
|
url = 'https://api.apollo.io/api/v1/mixed_people/search'
|
|
196
206
|
logger.debug(f"Making request to Apollo with payload: {data}")
|
|
197
207
|
|
|
@@ -202,6 +212,7 @@ async def lookup_person_in_apollo_by_name(
|
|
|
202
212
|
if response.status == 200:
|
|
203
213
|
result = await response.json()
|
|
204
214
|
logger.info("Successfully looked up person by name on Apollo.")
|
|
215
|
+
cache_output("lookup_person_in_apollo_by_name", key_item, result)
|
|
205
216
|
return result
|
|
206
217
|
elif response.status == 429:
|
|
207
218
|
msg = "Rate limit exceeded"
|
|
@@ -222,7 +233,6 @@ async def lookup_person_in_apollo_by_name(
|
|
|
222
233
|
logger.exception("Exception occurred while looking up person by name.")
|
|
223
234
|
return {'error': str(e)}
|
|
224
235
|
|
|
225
|
-
|
|
226
236
|
@assistant_tool
|
|
227
237
|
@backoff.on_exception(
|
|
228
238
|
backoff.expo,
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/check_email_validity_tools.py
RENAMED
|
@@ -220,6 +220,18 @@ async def check_email_validity_with_hunter(
|
|
|
220
220
|
"confidence": "low",
|
|
221
221
|
"is_valid": False
|
|
222
222
|
}
|
|
223
|
+
|
|
224
|
+
cache_key = f"{email_id}"
|
|
225
|
+
cached_response = retrieve_output("hunter_validate", cache_key)
|
|
226
|
+
if cached_response is not None:
|
|
227
|
+
logger.info("Cache hit for Hunter validate.")
|
|
228
|
+
if not cached_response:
|
|
229
|
+
return {
|
|
230
|
+
"email": email_id,
|
|
231
|
+
"confidence": "low",
|
|
232
|
+
"is_valid": False
|
|
233
|
+
}
|
|
234
|
+
return json.loads(cached_response[0])
|
|
223
235
|
|
|
224
236
|
HUNTER_API_KEY = get_hunter_access_token(tool_config)
|
|
225
237
|
if not HUNTER_API_KEY:
|
|
@@ -241,11 +253,14 @@ async def check_email_validity_with_hunter(
|
|
|
241
253
|
if response.status != 200:
|
|
242
254
|
content = await safe_read_json_or_text(response)
|
|
243
255
|
logger.warning(f"[Hunter] Non-200 status: {response.status} => {content}")
|
|
244
|
-
|
|
256
|
+
|
|
257
|
+
final_response = {
|
|
245
258
|
"email": email_id,
|
|
246
259
|
"confidence": "low",
|
|
247
260
|
"is_valid": False
|
|
248
261
|
}
|
|
262
|
+
cache_output("hunter_validate", cache_key, [json.dumps(final_response)])
|
|
263
|
+
return final_response
|
|
249
264
|
|
|
250
265
|
result = await response.json()
|
|
251
266
|
except Exception as ex:
|
|
@@ -266,6 +281,7 @@ async def check_email_validity_with_hunter(
|
|
|
266
281
|
"confidence": confidence,
|
|
267
282
|
"is_valid": is_valid
|
|
268
283
|
}
|
|
284
|
+
cache_output("hunter_validate", cache_key, [json.dumps(final_response)])
|
|
269
285
|
logger.info("Exiting check_email_validity_with_hunter.")
|
|
270
286
|
return final_response
|
|
271
287
|
|
|
@@ -8,6 +8,23 @@ def clean_nul_bytes(s: str) -> str:
|
|
|
8
8
|
s = s.replace('```markdown', '')
|
|
9
9
|
return s.replace('\x00', '')
|
|
10
10
|
|
|
11
|
+
def _remove_excluded_fields(data: Dict) -> Dict:
|
|
12
|
+
"""
|
|
13
|
+
Return a copy of `data` that excludes keys named 'id'
|
|
14
|
+
or that end in '_by', '_id', '_to', or '_at'.
|
|
15
|
+
"""
|
|
16
|
+
excluded_keys = {"id"}
|
|
17
|
+
excluded_endings = ["_by", "_id", "_to", "_at", "_status", "research_summary"]
|
|
18
|
+
|
|
19
|
+
cleaned = {}
|
|
20
|
+
for k, v in data.items():
|
|
21
|
+
if k in excluded_keys:
|
|
22
|
+
continue
|
|
23
|
+
if any(k.endswith(suffix) for suffix in excluded_endings):
|
|
24
|
+
continue
|
|
25
|
+
cleaned[k] = v
|
|
26
|
+
return cleaned
|
|
27
|
+
|
|
11
28
|
class LeadResearchInformation(BaseModel):
|
|
12
29
|
research_summary: str
|
|
13
30
|
|
|
@@ -20,7 +37,13 @@ async def research_lead_with_full_info_ai(
|
|
|
20
37
|
"""
|
|
21
38
|
Research on lead provided given input. Provide Detailed Summary.
|
|
22
39
|
"""
|
|
40
|
+
# Clean user properties (e.g. remove newlines, sanitize strings, etc.)
|
|
23
41
|
user_properties = cleanup_email_context(user_properties)
|
|
42
|
+
|
|
43
|
+
# Remove excluded fields from user_properties
|
|
44
|
+
user_properties = _remove_excluded_fields(user_properties)
|
|
45
|
+
|
|
46
|
+
# Optionally remove any known keys that should not appear (e.g. 'date_extracted')
|
|
24
47
|
user_properties.pop("date_extracted", None)
|
|
25
48
|
|
|
26
49
|
instructions = f"""
|
|
@@ -69,7 +92,7 @@ async def research_lead_with_full_info_ai(
|
|
|
69
92
|
response.research_summary = clean_nul_bytes(response.research_summary)
|
|
70
93
|
return response.model_dump()
|
|
71
94
|
else:
|
|
72
|
-
{"research_summary"
|
|
95
|
+
return {"research_summary": ""}
|
|
73
96
|
|
|
74
97
|
# --------------------------------------------
|
|
75
98
|
# COMPANY-RELATED MODELS & FUNCTION (FIXED)
|
|
@@ -94,9 +117,12 @@ async def research_company_with_full_info_ai(
|
|
|
94
117
|
Returns:
|
|
95
118
|
dict: The JSON response containing the detailed research summary of the company.
|
|
96
119
|
"""
|
|
120
|
+
# Clean company properties (e.g. remove newlines, sanitize strings, etc.)
|
|
97
121
|
company_properties = cleanup_email_context(company_properties)
|
|
98
122
|
|
|
99
|
-
#
|
|
123
|
+
# Remove excluded fields from company_properties
|
|
124
|
+
company_properties = _remove_excluded_fields(company_properties)
|
|
125
|
+
|
|
100
126
|
instructions = f"""
|
|
101
127
|
Please read the following company information and instructions, then produce a detailed summary of the company in the specified format.
|
|
102
128
|
---
|
|
@@ -130,11 +156,10 @@ async def research_company_with_full_info_ai(
|
|
|
130
156
|
"research_summary": "Detailed summary about the company. The summary should be neatly formatted in GitHub-Flavored Markdown, and include all the key information from the listed sections."
|
|
131
157
|
}}
|
|
132
158
|
"""
|
|
133
|
-
|
|
134
159
|
response, status = await get_structured_output_internal(
|
|
135
|
-
instructions,
|
|
136
|
-
CompanyResearchInformation,
|
|
137
|
-
model="gpt-4o",
|
|
160
|
+
instructions,
|
|
161
|
+
CompanyResearchInformation,
|
|
162
|
+
model="gpt-4o",
|
|
138
163
|
use_web_search=True,
|
|
139
164
|
tool_config=tool_config
|
|
140
165
|
)
|
|
@@ -142,4 +167,4 @@ async def research_company_with_full_info_ai(
|
|
|
142
167
|
response.research_summary = clean_nul_bytes(response.research_summary)
|
|
143
168
|
return response.model_dump()
|
|
144
169
|
else:
|
|
145
|
-
return {"research_summary"
|
|
170
|
+
return {"research_summary": ""}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/check_linkedin_url_validity.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/compose_three_step_workflow.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/extract_email_content_for_llm.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/generate_linkedin_connect_message.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openai_assistant_and_file_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/openapi_tool/openapi_tool.py
RENAMED
|
File without changes
|
{dhisana-0.0.1.dev101 → dhisana-0.0.1.dev102}/src/dhisana/utils/parse_linkedin_messages_txt.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|