dhisana 0.0.1.dev121__tar.gz → 0.0.1.dev231__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 (126) hide show
  1. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/PKG-INFO +1 -1
  2. dhisana-0.0.1.dev231/README.md +257 -0
  3. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/setup.py +1 -1
  4. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/schemas/common.py +9 -1
  5. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/schemas/sales.py +200 -21
  6. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/apollo_tools.py +736 -114
  7. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/built_with_api_tools.py +4 -2
  8. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/check_email_validity_tools.py +35 -17
  9. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/check_linkedin_url_validity.py +34 -6
  10. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/clay_tools.py +3 -1
  11. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/compose_search_query.py +7 -2
  12. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/dataframe_tools.py +2 -2
  13. dhisana-0.0.1.dev231/src/dhisana/utils/email_body_utils.py +72 -0
  14. dhisana-0.0.1.dev231/src/dhisana/utils/email_provider.py +375 -0
  15. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/enrich_lead_information.py +162 -46
  16. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/fetch_openai_config.py +9 -3
  17. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/generate_email.py +10 -2
  18. dhisana-0.0.1.dev231/src/dhisana/utils/generate_email_response.py +465 -0
  19. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/generate_linkedin_connect_message.py +9 -2
  20. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/generate_linkedin_response_message.py +137 -73
  21. dhisana-0.0.1.dev231/src/dhisana/utils/generate_structured_output_internal.py +462 -0
  22. dhisana-0.0.1.dev231/src/dhisana/utils/google_custom_search.py +267 -0
  23. dhisana-0.0.1.dev231/src/dhisana/utils/google_oauth_tools.py +675 -0
  24. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/google_workspace_tools.py +192 -11
  25. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/hubspot_clearbit.py +3 -1
  26. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/hubspot_crm_tools.py +718 -272
  27. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/instantly_tools.py +3 -1
  28. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/lusha_tools.py +8 -3
  29. dhisana-0.0.1.dev231/src/dhisana/utils/mailgun_tools.py +150 -0
  30. dhisana-0.0.1.dev231/src/dhisana/utils/microsoft365_tools.py +407 -0
  31. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/openai_assistant_and_file_utils.py +3 -3
  32. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/openai_helpers.py +6 -4
  33. dhisana-0.0.1.dev231/src/dhisana/utils/profile.py +37 -0
  34. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/proxy_curl_tools.py +298 -60
  35. dhisana-0.0.1.dev231/src/dhisana/utils/proxycurl_search_leads.py +426 -0
  36. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/research_lead.py +3 -3
  37. dhisana-0.0.1.dev231/src/dhisana/utils/salesforce_crm_tools.py +477 -0
  38. dhisana-0.0.1.dev231/src/dhisana/utils/search_router.py +131 -0
  39. dhisana-0.0.1.dev231/src/dhisana/utils/search_router_jobs.py +51 -0
  40. dhisana-0.0.1.dev231/src/dhisana/utils/sendgrid_tools.py +152 -0
  41. dhisana-0.0.1.dev231/src/dhisana/utils/serarch_router_local_business.py +75 -0
  42. dhisana-0.0.1.dev231/src/dhisana/utils/serpapi_additional_tools.py +290 -0
  43. dhisana-0.0.1.dev231/src/dhisana/utils/serpapi_google_jobs.py +117 -0
  44. dhisana-0.0.1.dev231/src/dhisana/utils/serpapi_google_search.py +188 -0
  45. dhisana-0.0.1.dev231/src/dhisana/utils/serpapi_local_business_search.py +129 -0
  46. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/serpapi_search_tools.py +351 -422
  47. dhisana-0.0.1.dev231/src/dhisana/utils/serperdev_google_jobs.py +125 -0
  48. dhisana-0.0.1.dev231/src/dhisana/utils/serperdev_local_business.py +154 -0
  49. dhisana-0.0.1.dev231/src/dhisana/utils/serperdev_search.py +233 -0
  50. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/smtp_email_tools.py +74 -5
  51. dhisana-0.0.1.dev231/src/dhisana/utils/test_connect.py +1669 -0
  52. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/trasform_json.py +2 -1
  53. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/zoominfo_tools.py +2 -2
  54. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/workflow/test.py +1 -1
  55. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana.egg-info/PKG-INFO +1 -1
  56. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana.egg-info/SOURCES.txt +28 -1
  57. dhisana-0.0.1.dev231/tests/test_apollo_company_search.py +216 -0
  58. dhisana-0.0.1.dev231/tests/test_apollo_lead_search.py +119 -0
  59. dhisana-0.0.1.dev231/tests/test_connectivity.py +102 -0
  60. dhisana-0.0.1.dev231/tests/test_email_body_utils.py +23 -0
  61. dhisana-0.0.1.dev231/tests/test_google_document.py +119 -0
  62. dhisana-0.0.1.dev231/tests/test_hubspot_call_logs.py +79 -0
  63. dhisana-0.0.1.dev231/tests/test_linkedin_serper.py +55 -0
  64. dhisana-0.0.1.dev231/tests/test_mcp_connectivity.py +28 -0
  65. dhisana-0.0.1.dev231/tests/test_proxycurl_get_company_search_id.py +170 -0
  66. dhisana-0.0.1.dev231/tests/test_proxycurl_job_count.py +61 -0
  67. dhisana-0.0.1.dev231/tests/test_structured_output_with_mcp.py +56 -0
  68. dhisana-0.0.1.dev121/README.md +0 -141
  69. dhisana-0.0.1.dev121/src/dhisana/utils/email_provider.py +0 -235
  70. dhisana-0.0.1.dev121/src/dhisana/utils/generate_email_response.py +0 -305
  71. dhisana-0.0.1.dev121/src/dhisana/utils/generate_structured_output_internal.py +0 -255
  72. dhisana-0.0.1.dev121/src/dhisana/utils/google_custom_search.py +0 -161
  73. dhisana-0.0.1.dev121/src/dhisana/utils/salesforce_crm_tools.py +0 -204
  74. dhisana-0.0.1.dev121/src/dhisana/utils/sendgrid_tools.py +0 -117
  75. dhisana-0.0.1.dev121/src/dhisana/utils/test_connect.py +0 -543
  76. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/pyproject.toml +0 -0
  77. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/setup.cfg +0 -0
  78. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/__init__.py +0 -0
  79. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/cli/__init__.py +0 -0
  80. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/cli/cli.py +0 -0
  81. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/cli/datasets.py +0 -0
  82. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/cli/models.py +0 -0
  83. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/cli/predictions.py +0 -0
  84. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/schemas/__init__.py +0 -0
  85. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/ui/__init__.py +0 -0
  86. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/ui/components.py +0 -0
  87. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/__init__.py +0 -0
  88. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/add_mapping.py +0 -0
  89. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/agent_tools.py +0 -0
  90. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/assistant_tool_tag.py +0 -0
  91. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/cache_output_tools.py +0 -0
  92. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/cache_output_tools_local.py +0 -0
  93. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/check_for_intent_signal.py +0 -0
  94. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/clean_properties.py +0 -0
  95. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/company_utils.py +0 -0
  96. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/compose_salesnav_query.py +0 -0
  97. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/compose_three_step_workflow.py +0 -0
  98. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/composite_tools.py +0 -0
  99. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/domain_parser.py +0 -0
  100. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/email_parse_helpers.py +0 -0
  101. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/extract_email_content_for_llm.py +0 -0
  102. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/field_validators.py +0 -0
  103. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/g2_tools.py +0 -0
  104. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/generate_content.py +0 -0
  105. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/generate_flow.py +0 -0
  106. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/generate_leads_salesnav.py +0 -0
  107. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/linkedin_crawler.py +0 -0
  108. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/openapi_spec_to_tools.py +0 -0
  109. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/openapi_tool/__init__.py +0 -0
  110. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/openapi_tool/api_models.py +0 -0
  111. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/openapi_tool/convert_openai_spec_to_tool.py +0 -0
  112. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/openapi_tool/openapi_tool.py +0 -0
  113. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/parse_linkedin_messages_txt.py +0 -0
  114. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/python_function_to_tools.py +0 -0
  115. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/sales_navigator_crawler.py +0 -0
  116. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/web_download_parse_tools.py +0 -0
  117. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/utils/workflow_code_model.py +0 -0
  118. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/workflow/__init__.py +0 -0
  119. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/workflow/agent.py +0 -0
  120. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/workflow/flow.py +0 -0
  121. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana/workflow/task.py +0 -0
  122. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana.egg-info/dependency_links.txt +0 -0
  123. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana.egg-info/entry_points.txt +0 -0
  124. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana.egg-info/requires.txt +0 -0
  125. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/src/dhisana.egg-info/top_level.txt +0 -0
  126. {dhisana-0.0.1.dev121 → dhisana-0.0.1.dev231}/tests/test_agent_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhisana
3
- Version: 0.0.1.dev121
3
+ Version: 0.0.1.dev231
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
@@ -0,0 +1,257 @@
1
+ # Dhisana Python SDK
2
+
3
+ A Python SDK for interacting with Dhisana AI services.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install dhisana
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```python
14
+ from dhisana.utils.agent_tools import (
15
+ search_google_maps,
16
+ enrich_people_with_apollo,
17
+ search_google,
18
+ search_google_jobs,
19
+ search_google_news,
20
+ get_html_content_from_url,
21
+ parse_html_content,
22
+ extract_image_links,
23
+ extract_head_section_from_html_content,
24
+ get_email_if_exists,
25
+ search_crunchbase,
26
+ search_people_with_apollo,
27
+ search_companies_with_apollo,
28
+ enrich_company_with_apollo,
29
+ get_job_postings_from_apollo
30
+ )
31
+ # Your code here
32
+ ```
33
+
34
+ ## Steps to Create and Publish the Package
35
+
36
+ ### Ensure you have the latest versions of setuptools and wheel
37
+
38
+ ```bash
39
+ pip install --upgrade setuptools wheel
40
+ ```
41
+
42
+ ### Build the Package
43
+
44
+ ```bash
45
+ pip install .
46
+ ```
47
+
48
+ ### Upload to PyPI
49
+
50
+ First, install twine:
51
+
52
+ ```bash
53
+ pip install --upgrade build twine
54
+ python -m build
55
+ pip install twine
56
+ ```
57
+
58
+ ### Then upload your package (you'll need a PyPI account)
59
+
60
+ ```bash
61
+ twine upload dist/\*
62
+ ```
63
+
64
+ ### Install the Package Locally for Testing
65
+
66
+ You can install the package locally to test it before uploading:
67
+
68
+ ```bash
69
+ pip install -e .
70
+ ```
71
+
72
+ The -e flag installs the package in editable mode, which is useful during development.
73
+
74
+ ## Run Tests
75
+
76
+ ```bash
77
+ pip install pytest
78
+ pytest tests/
79
+ ```
80
+
81
+ ### Using the Package in Other Projects
82
+
83
+ Once your package is published to PyPI, other users can install it using:
84
+
85
+ ```bash
86
+ pip install dhisana
87
+ ```
88
+
89
+ They can then import your SDK as:
90
+
91
+ ```bash
92
+ from dhisana.utils.agent_tools import (
93
+ search_google_maps,
94
+ enrich_people_with_apollo,
95
+ search_google,
96
+ search_google_jobs,
97
+ search_google_news,
98
+ get_html_content_from_url,
99
+ parse_html_content,
100
+ extract_image_links,
101
+ extract_head_section_from_html_content,
102
+ get_email_if_exists,
103
+ search_crunchbase,
104
+ search_people_with_apollo,
105
+ search_companies_with_apollo,
106
+ enrich_company_with_apollo,
107
+ get_job_postings_from_apollo
108
+ )
109
+
110
+ # Use the functionalities provided by your SDK
111
+ ```
112
+
113
+ ### To use locally
114
+
115
+ ```bash
116
+ pip install -e /path/to/other/project
117
+ ```
118
+
119
+ ### To use CLI
120
+
121
+ You can use the CLI provided by the Dhisana AI SDK. To see the available commands and options, use:
122
+
123
+ ```bash
124
+ dhisana --help
125
+ ```
126
+
127
+ This will display:
128
+
129
+ ```bash
130
+ Usage: dhisana [OPTIONS] COMMAND [ARGS]...
131
+
132
+ Dhisana AI SDK CLI.
133
+
134
+ Options:
135
+ --help Show this message and exit.
136
+
137
+ Commands:
138
+ dataset-cli Commands for managing datasets.
139
+ model-cli Commands for managing models.
140
+ prediction-cli Commands for running predictions.
141
+ ```
142
+
143
+ ## Proxycurl Job Leads Example
144
+
145
+ Set `PROXY_CURL_API_KEY` in your environment before running functions that call Proxycurl.
146
+
147
+ ```bash
148
+ export PROXY_CURL_API_KEY=your_api_key
149
+ ```
150
+
151
+ Example usage to search for SDR roles and retrieve hiring manager leads:
152
+
153
+ ```python
154
+ import asyncio
155
+ from dhisana.utils.proxy_curl_tools import find_leads_by_job_openings_proxy_curl
156
+
157
+ async def main():
158
+ leads = await find_leads_by_job_openings_proxy_curl(
159
+ {"job_title": "SDR", "location": "United States"},
160
+ hiring_manager_roles=["VP of Sales", "Head of Sales"],
161
+ )
162
+ print(leads)
163
+
164
+ asyncio.run(main())
165
+ ```
166
+
167
+ ## Proxycurl Job Search Example
168
+
169
+ Use `proxycurl_job_search` to list jobs posted by a company. Parameters mirror
170
+ Proxycurl's job search endpoint.
171
+
172
+ ### Parameters
173
+
174
+ - `job_type` – one of `full-time`, `part-time`, `contract`, `internship`,
175
+ `temporary`, `volunteer`, or `anything`.
176
+ - `experience_level` – `internship`, `entry_level`, `associate`,
177
+ `mid_senior_level`, `director`, or `anything`.
178
+ - `when` – posted time such as `yesterday`, `past-week`, `past-month`, or
179
+ `anytime`.
180
+ - `flexibility` – `remote`, `on-site`, `hybrid`, or `anything`.
181
+ - `geo_id` – location identifier, e.g. `92000000` for worldwide.
182
+ - `keyword` – keyword to match in the job title.
183
+ - `search_id` – company search identifier from the Company Profile API.
184
+
185
+ Example usage:
186
+
187
+ ```python
188
+ import asyncio
189
+ from dhisana.utils.proxycurl_search_leads import JobSearchParams, proxycurl_job_search
190
+
191
+ async def main():
192
+ jobs = await proxycurl_job_search(
193
+ JobSearchParams(
194
+ search_id="2790400",
195
+ keyword="engineer",
196
+ job_type="full-time",
197
+ experience_level="mid_senior_level",
198
+ when="past-month",
199
+ flexibility="remote",
200
+ geo_id=92000000,
201
+ ),
202
+ max_entries=2,
203
+ )
204
+ print(jobs)
205
+
206
+ asyncio.run(main())
207
+ ```
208
+
209
+ ## Proxycurl Get Company Search ID Example
210
+
211
+ Use `proxycurl_get_company_search_id` to retrieve a company's search ID, which is required for other Proxycurl operations like job searches. This function calls Proxycurl's Company Profile endpoint.
212
+
213
+ ### Function Parameters
214
+
215
+ - `company_url` – LinkedIn company profile URL (e.g., `https://www.linkedin.com/company/microsoft/`)
216
+ - `tool_config` – Optional tool configuration containing API key
217
+
218
+ ### Return Value
219
+
220
+ Returns a dictionary with:
221
+
222
+ - `search_id` – The company's search ID (required for job operations)
223
+ - `name` – Company name
224
+ - `linkedin_internal_id` – LinkedIn's internal company ID
225
+ - `industry` – Company industry
226
+ - `company_url` – The original URL provided
227
+ - `error` – Error message (if any errors occurred)
228
+
229
+ Example usage:
230
+
231
+ ```python
232
+ import asyncio
233
+ from dhisana.utils.proxycurl_search_leads import (
234
+ proxycurl_get_company_search_id,
235
+ proxycurl_job_count,
236
+ JobSearchParams
237
+ )
238
+
239
+ async def main():
240
+ # Get company search ID
241
+ company_result = await proxycurl_get_company_search_id(
242
+ "https://www.linkedin.com/company/microsoft/"
243
+ )
244
+
245
+ if company_result.get("search_id"):
246
+ print(f"Company: {company_result['name']}")
247
+ print(f"Search ID: {company_result['search_id']}")
248
+
249
+ # Use the search ID for job operations
250
+ job_params = JobSearchParams(search_id=company_result["search_id"])
251
+ job_count = await proxycurl_job_count(job_params)
252
+ print(f"Total jobs: {job_count.get('count', 0)}")
253
+ else:
254
+ print(f"Error: {company_result.get('error')}")
255
+
256
+ asyncio.run(main())
257
+ ```
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='dhisana',
5
- version='0.0.1-dev121',
5
+ version='0.0.1-dev231',
6
6
  description='A Python SDK for Dhisana AI Platform',
7
7
  author='Admin',
8
8
  author_email='contact@dhisana.ai',
@@ -364,6 +364,12 @@ class Integration(IntegrationBase):
364
364
  Integration.model_rebuild()
365
365
  IntegrationUpdate.model_rebuild()
366
366
 
367
+ class BodyFormat(str, Enum):
368
+ AUTO = "auto"
369
+ HTML = "html"
370
+ TEXT = "text"
371
+
372
+
367
373
  class SendEmailContext(BaseModel):
368
374
  recipient: str
369
375
  subject: str
@@ -371,6 +377,7 @@ class SendEmailContext(BaseModel):
371
377
  sender_name: str
372
378
  sender_email: str
373
379
  labels: Optional[List[str]]
380
+ body_format: BodyFormat = BodyFormat.AUTO
374
381
 
375
382
  class QueryEmailContext(BaseModel):
376
383
  start_time: str
@@ -386,4 +393,5 @@ class ReplyEmailContext(BaseModel):
386
393
  sender_email: str
387
394
  sender_name: str
388
395
  mark_as_read: str = "True"
389
- add_labels: Optional[List[str]] = None
396
+ add_labels: Optional[List[str]] = None
397
+ reply_body_format: BodyFormat = BodyFormat.AUTO
@@ -1,5 +1,7 @@
1
+ import json
2
+
1
3
  from uuid import UUID
2
- from pydantic import BaseModel, Field
4
+ from pydantic import BaseModel, Field, field_validator
3
5
  from typing import List, Optional, Dict, Any
4
6
  from enum import Enum
5
7
  from typing import Optional, List, Dict, Literal
@@ -10,14 +12,20 @@ from typing import Optional, List, Dict, Literal
10
12
  # -----------------------------
11
13
 
12
14
  class Lead(BaseModel):
13
- id: Optional[str] = None
15
+ id: Optional[UUID] = None
14
16
  full_name: Optional[str] = None
15
17
  first_name: Optional[str] = None
16
18
  last_name: Optional[str] = None
17
19
  email: Optional[str] = None
18
20
  user_linkedin_url: Optional[str] = None
19
21
  user_linkedin_salesnav_url: Optional[str] = None
22
+ organization_linkedin_url: Optional[str] = None
23
+ organization_linkedin_salesnav_url: Optional[str] = None
24
+ linkedin_follower_count: Optional[int] = None
20
25
  primary_domain_of_organization: Optional[str] = None
26
+ twitter_handle: Optional[str] = None
27
+ twitch_handle: Optional[str] = None
28
+ github_handle: Optional[str] = None
21
29
  job_title: Optional[str] = None
22
30
  phone: Optional[str] = None
23
31
  headline: Optional[str] = None
@@ -25,25 +33,69 @@ class Lead(BaseModel):
25
33
  organization_name: Optional[str] = None
26
34
  organization_website: Optional[str] = None
27
35
  summary_about_lead: Optional[str] = None
36
+
37
+ qualification_score: Optional[float] = None
38
+ qualification_reason: Optional[str] = None
39
+ revenue: Optional[str] = None
40
+ company_size: Optional[str] = None
41
+ industry: Optional[str] = None
42
+
43
+ keywords: Optional[Any] = None
44
+ tags: List[str] = []
45
+ notes: List[str] = []
46
+ additional_properties: Optional[Dict[str, Any]] = {}
28
47
  workflow_stage: Optional[str] = None
29
- assigned_to: Optional[str] = None
30
- engaged: Optional[bool] = None
48
+
49
+ engaged: bool = False
31
50
  last_contact: Optional[int] = None
32
- additional_properties: Optional[Dict[str, str]] = None
33
51
  research_summary: Optional[str] = None
34
52
  task_ids: Optional[List[str]] = None
35
- email_validation_status: Optional[
36
- Literal["not_started", "in_progress", "valid", "invalid"]
37
- ] = None
38
- linkedin_validation_status: Optional[
39
- Literal["not_started", "in_progress", "valid", "invalid"]
40
- ] = None
41
- research_status: Optional[
42
- Literal["not_started", "in_progress", "done", "failed"]
43
- ] = None
44
- enchrichment_status: Optional[
45
- Literal["not_started", "in_progress", "done", "failed"]
46
- ] = None
53
+ email_validation_status: Optional[str] = None
54
+ linkedin_validation_status: Optional[str] = None
55
+ research_status: Optional[str] = None
56
+ enchrichment_status: Optional[str] = None
57
+
58
+
59
+ @field_validator("linkedin_follower_count", mode="before")
60
+ @classmethod
61
+ def parse_linkedin_follower_count(cls, v):
62
+ if v is None or v == "":
63
+ return None
64
+ if isinstance(v, str):
65
+ v = v.strip()
66
+ if v == "":
67
+ return None
68
+ try:
69
+ return int(v)
70
+ except ValueError:
71
+ raise ValueError("linkedin_follower_count must be an integer")
72
+ return v
73
+
74
+ @field_validator("notes", mode="before")
75
+ @classmethod
76
+ def ensure_notes_list(cls, v):
77
+ """Coerce notes to a list of strings.
78
+ Handles legacy cases where the DB may contain a scalar or JSON string.
79
+ """
80
+ if v is None:
81
+ return []
82
+ if isinstance(v, list):
83
+ # Ensure all elements are strings
84
+ return [str(item) if not isinstance(item, str) else item for item in v]
85
+ if isinstance(v, str):
86
+ # Try to parse JSON array; if not, wrap as single-note list
87
+ try:
88
+ parsed = json.loads(v)
89
+ if isinstance(parsed, list):
90
+ return [str(item) if not isinstance(item, str) else item for item in parsed]
91
+ except Exception:
92
+ pass
93
+ return [v]
94
+ # Fallback: wrap any other scalar/object as a single string entry
95
+ try:
96
+ return [json.dumps(v)]
97
+ except Exception:
98
+ return [str(v)]
47
99
 
48
100
 
49
101
  class LeadList(BaseModel):
@@ -242,6 +294,7 @@ class MessageGenerationInstructions(BaseModel):
242
294
  """
243
295
  instructions_to_generate_message: Optional[str] = None
244
296
  prompt_engineering_guidance: Optional[PromptEngineeringGuidance] = None
297
+ use_cache: Optional[bool] = True
245
298
 
246
299
  class CampaignContext(BaseModel):
247
300
  """
@@ -303,6 +356,7 @@ class MessageItem(BaseModel):
303
356
  ...,
304
357
  description="Body of the message in plain text"
305
358
  )
359
+ html_body: Optional[str] = None
306
360
 
307
361
  class MessageResponse(BaseModel):
308
362
  """
@@ -438,14 +492,14 @@ class HubSpotLeadInformation(BaseModel):
438
492
  organization_name: str = Field("", description="Current Company where lead works")
439
493
  organization_website: str = Field("", description="Current Company website of the lead")
440
494
  organization_linkedin_url : str = Field("", description="Company LinkedIn URL")
441
- additional_properties: Optional[Dict[str, str]] = None
495
+ additional_properties: Optional[Dict[str, Any]] = None
442
496
 
443
497
  class HubSpotCompanyinformation(BaseModel):
444
498
  primary_domain_of_organization: str = Field("", description="Primary domain of the organization")
445
499
  organization_name: str = Field("", description="Current Company where lead works")
446
500
  organization_website: str = Field("", description="Current Company website of the lead")
447
501
  organization_linkedin_url : str = Field("", description="Company LinkedIn URL")
448
- additional_properties: Optional[Dict[str, str]] = None
502
+ additional_properties: Optional[Dict[str, Any]] = None
449
503
 
450
504
 
451
505
  # --------------------------------------------------------------------
@@ -462,6 +516,7 @@ HUBSPOT_TO_LEAD_MAPPING = {
462
516
  "address": "lead_location", # You can choose "city", "state", etc. if you prefer
463
517
  "city": "lead_location",
464
518
  "domain": "primary_domain_of_organization",
519
+ "hs_linkedin_url": "user_linkedin_url",
465
520
  }
466
521
 
467
522
  class SmartListStatus(str, Enum):
@@ -482,6 +537,11 @@ class SmartListSourceType(str, Enum):
482
537
  GOOGLE_SHEETS = "GOOGLE_SHEETS"
483
538
  CUSTOM_WEBSITE = "CUSTOM_WEBSITE"
484
539
  GITHUB = "GITHUB"
540
+ ICP_SEARCH = "ICP_SEARCH"
541
+ LOCAL_BUSINESS = "LOCAL_BUSINESS"
542
+ GOOGLE_JOBS = "GOOGLE_JOBS"
543
+ WEBHOOK = "WEBHOOK"
544
+ GOOGLE_CUSTOM_SITE_SEARCH = "GOOGLE_CUSTOM_SITE_SEARCH"
485
545
 
486
546
  class SourceConfiguration(BaseModel):
487
547
  """
@@ -577,13 +637,18 @@ class SmartListLead(BaseModel):
577
637
  organization_name: Optional[str] = None
578
638
  organization_website: Optional[str] = None
579
639
  summary_about_lead: Optional[str] = None
580
- keywords: Optional[List[str]] = None
640
+ keywords: Optional[Any] = None
581
641
  additional_properties: Optional[Dict[str, Any]] = None
582
642
  research_summary: Optional[str] = None
583
643
 
584
644
  qualification_score: Optional[float] = None
585
645
  qualification_reason: Optional[str] = None
586
646
  source: Optional[str] = None
647
+
648
+ email_validation_status: Optional[str] = None
649
+ linkedin_validation_status: Optional[str] = None
650
+ research_status: Optional[str] = None
651
+ enchrichment_status: Optional[str] = None
587
652
 
588
653
  agent_instance_id: Optional[UUID] = None
589
654
  organization_id: Optional[UUID] = None
@@ -595,7 +660,6 @@ class SmartListLead(BaseModel):
595
660
  revenue: Optional[str] = None
596
661
  company_size: Optional[str] = None
597
662
  industry: Optional[str] = None
598
-
599
663
  class Config:
600
664
  from_attributes = True
601
665
 
@@ -760,3 +824,118 @@ class LeadsQueryFilters(BaseModel):
760
824
  description="Ranges for organization number of employees."
761
825
  )
762
826
 
827
+
828
+ class CompanyQueryFilters(BaseModel):
829
+ """
830
+ Defines the filter parameters for querying companies/organizations in the Apollo database.
831
+ All fields are optional and default to None if not specified by user.
832
+ """
833
+
834
+ # Core company search parameters
835
+ organization_locations: Optional[List[str]] = Field(
836
+ default=None,
837
+ description="List of organization headquarters locations (city, state, country)."
838
+ )
839
+
840
+ organization_num_employees_ranges: Optional[List[str]] = Field(
841
+ default=None,
842
+ description="Employee count ranges, e.g. ['1,10', '11,50', '51,200']. Use specific ranges."
843
+ )
844
+
845
+ min_employees: Optional[int] = Field(
846
+ default=None,
847
+ description="Minimum number of employees (>=1). Internally converted to a numeric range."
848
+ )
849
+
850
+ max_employees: Optional[int] = Field(
851
+ default=None,
852
+ description="Maximum number of employees (<=100000). Internally converted to a numeric range."
853
+ )
854
+
855
+ organization_industries: Optional[List[str]] = Field(
856
+ default=None,
857
+ description="List of organization industries."
858
+ )
859
+
860
+ organization_industry_tag_ids: Optional[List[str]] = Field(
861
+ default=None,
862
+ description="List of industry tag IDs, e.g. ['5567cd4773696439b10b0000']."
863
+ )
864
+
865
+ # Revenue filters
866
+ revenue_range_min: Optional[int] = Field(
867
+ default=None,
868
+ description="Minimum company revenue in USD."
869
+ )
870
+
871
+ revenue_range_max: Optional[int] = Field(
872
+ default=None,
873
+ description="Maximum company revenue in USD."
874
+ )
875
+
876
+ # Funding and growth
877
+ organization_latest_funding_stage_cd: Optional[List[str]] = Field(
878
+ default=None,
879
+ description="List of funding stage codes, e.g. ['2', '3', '10']."
880
+ )
881
+
882
+ # Technology and keywords
883
+ currently_using_any_of_technology_uids: Optional[List[str]] = Field(
884
+ default=None,
885
+ description="Technology UIDs used by the organization, e.g. ['google_font_api']."
886
+ )
887
+
888
+ q_keywords: Optional[str] = Field(
889
+ default=None,
890
+ description="Keywords to search for in company descriptions, names, etc."
891
+ )
892
+
893
+ q_organization_domains: Optional[List[str]] = Field(
894
+ default=None,
895
+ description="Specific company domains to search for, e.g. ['microsoft.com', 'google.com']."
896
+ )
897
+
898
+ # Company-specific filters
899
+ organization_ids: Optional[List[str]] = Field(
900
+ default=None,
901
+ description="Specific Apollo organization IDs to include."
902
+ )
903
+
904
+ not_organization_ids: Optional[List[str]] = Field(
905
+ default=None,
906
+ description="Apollo organization IDs to exclude from results."
907
+ )
908
+
909
+ # Search lists
910
+ q_organization_search_list_id: Optional[str] = Field(
911
+ default=None,
912
+ description="Include only organizations in a specific search list."
913
+ )
914
+
915
+ q_not_organization_search_list_id: Optional[str] = Field(
916
+ default=None,
917
+ description="Exclude organizations in a specific search list."
918
+ )
919
+
920
+ # Sorting
921
+ sort_by_field: Optional[str] = Field(
922
+ default=None,
923
+ description="Sort field, e.g. 'name', 'employee_count', 'last_updated', etc."
924
+ )
925
+
926
+ sort_ascending: Optional[bool] = Field(
927
+ default=None,
928
+ description="Sort ascending (True) or descending (False)."
929
+ )
930
+
931
+ # Additional filters that might be useful
932
+ organization_founded_year_min: Optional[int] = Field(
933
+ default=None,
934
+ description="Minimum founding year for the organization."
935
+ )
936
+
937
+ organization_founded_year_max: Optional[int] = Field(
938
+ default=None,
939
+ description="Maximum founding year for the organization."
940
+ )
941
+