dhisana 0.0.1.dev9__tar.gz → 0.0.1.dev10__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 (43) hide show
  1. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/PKG-INFO +1 -1
  2. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/setup.py +1 -1
  3. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/google_workspace_tools.py +183 -0
  4. dhisana-0.0.1.dev10/src/dhisana/utils/hubspot_crm_tools.py +1126 -0
  5. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/openai_helpers.py +65 -39
  6. dhisana-0.0.1.dev10/src/dhisana/utils/serpapi_search_tools.py +227 -0
  7. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/web_download_parse_tools.py +11 -0
  8. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana.egg-info/PKG-INFO +1 -1
  9. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana.egg-info/SOURCES.txt +1 -0
  10. dhisana-0.0.1.dev9/src/dhisana/utils/hubspot_crm_tools.py +0 -598
  11. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/README.md +0 -0
  12. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/pyproject.toml +0 -0
  13. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/setup.cfg +0 -0
  14. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/__init__.py +0 -0
  15. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/cli/__init__.py +0 -0
  16. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/cli/cli.py +0 -0
  17. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/cli/datasets.py +0 -0
  18. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/cli/models.py +0 -0
  19. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/cli/predictions.py +0 -0
  20. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/ui/__init__.py +0 -0
  21. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/ui/components.py +0 -0
  22. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/__init__.py +0 -0
  23. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/agent_tools.py +0 -0
  24. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/apollo_tools.py +0 -0
  25. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/assistant_tool_tag.py +0 -0
  26. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/check_email_validity_tools.py +0 -0
  27. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/dataframe_tools.py +0 -0
  28. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/linkedin_crawler.py +0 -0
  29. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/openapi_spec_to_tools.py +0 -0
  30. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/openapi_tool/__init__.py +0 -0
  31. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/openapi_tool/api_models.py +0 -0
  32. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/openapi_tool/convert_openai_spec_to_tool.py +0 -0
  33. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/openapi_tool/openapi_tool.py +0 -0
  34. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/python_function_to_tools.py +0 -0
  35. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/salesforce_crm_tools.py +0 -0
  36. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/utils/tools_json.py +0 -0
  37. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/workflow/__init__.py +0 -0
  38. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana/workflow/task.py +0 -0
  39. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana.egg-info/dependency_links.txt +0 -0
  40. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana.egg-info/entry_points.txt +0 -0
  41. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana.egg-info/requires.txt +0 -0
  42. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/src/dhisana.egg-info/top_level.txt +0 -0
  43. {dhisana-0.0.1.dev9 → dhisana-0.0.1.dev10}/tests/test_agent_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dhisana
3
- Version: 0.0.1.dev9
3
+ Version: 0.0.1.dev10
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-dev9',
5
+ version='0.0.1-dev10',
6
6
  description='A Python SDK for Dhisana AI Platform',
7
7
  author='Admin',
8
8
  author_email='contact@dhisana.ai',
@@ -16,6 +16,8 @@ from googleapiclient.errors import HttpError
16
16
  import datetime
17
17
  from dhisana.utils.assistant_tool_tag import assistant_tool
18
18
 
19
+
20
+
19
21
  def convert_base_64_json(base64_string):
20
22
  """
21
23
  Convert a base64 encoded string to a JSON string.
@@ -445,6 +447,187 @@ async def list_emails_in_time_range_async(start_time: str, end_time: str, unread
445
447
 
446
448
  return email_details
447
449
 
450
+
451
+ @assistant_tool
452
+ async def fetch_last_n_sent_messages(recipient_email: str, num_messages: int) -> List[Dict[str, Any]]:
453
+ """
454
+ Fetch the last n messages sent to a specific recipient using the Gmail API with a service account.
455
+ The service account must have domain-wide delegation to impersonate the sender.
456
+
457
+ :param recipient_email: The recipient's email address.
458
+ :param num_messages: The number of recent messages to fetch.
459
+ :return: A list of email message details.
460
+ """
461
+ # Retrieve the service account JSON and email for automation from environment variables
462
+ service_account_base64 = os.getenv('GOOGLE_SERVICE_KEY')
463
+ automationemails = os.getenv('EMAIL_FOR_AUTOMATION')
464
+ if not service_account_base64 or not automationemails:
465
+ raise EnvironmentError("Required environment variables are not set.")
466
+
467
+ allowed_emails_for_automation = automationemails.split(",")
468
+ if not allowed_emails_for_automation:
469
+ raise EnvironmentError("No allowed emails for automation found in environment variables.")
470
+
471
+ mailbox_email = allowed_emails_for_automation[0]
472
+
473
+ # Function to convert base64-encoded JSON to a string
474
+ def convert_base_64_json(base64_json: str) -> str:
475
+ return base64.b64decode(base64_json).decode('utf-8')
476
+
477
+ service_account_json = convert_base_64_json(service_account_base64)
478
+
479
+ # Parse the JSON string into a dictionary
480
+ service_account_info = json.loads(service_account_json)
481
+
482
+ # Define the required scope for reading emails via Gmail API
483
+ SCOPES = ['https://mail.google.com/']
484
+
485
+ # Authenticate using the service account info and impersonate the email for automation
486
+ credentials = service_account.Credentials.from_service_account_info(
487
+ service_account_info, scopes=SCOPES
488
+ ).with_subject(mailbox_email)
489
+
490
+ # Refresh the token if necessary
491
+ if not credentials.valid:
492
+ request = Request()
493
+ credentials.refresh(request)
494
+
495
+ # Get the access token
496
+ access_token = credentials.token
497
+
498
+ # Define the Gmail API endpoint for listing messages
499
+ gmail_api_url = 'https://gmail.googleapis.com/gmail/v1/users/me/messages'
500
+
501
+ # Create the query parameters for the recipient email
502
+ query = f'to:{recipient_email}'
503
+
504
+ # Prepare the headers
505
+ headers = {
506
+ 'Authorization': f'Bearer {access_token}'
507
+ }
508
+
509
+ # Prepare the parameters
510
+ params = {
511
+ 'q': query,
512
+ 'maxResults': num_messages
513
+ }
514
+
515
+ async with httpx.AsyncClient() as client:
516
+ response = await client.get(gmail_api_url, headers=headers, params=params)
517
+ response.raise_for_status() # Raise an exception for HTTP errors
518
+ messages = response.json().get('messages', [])
519
+
520
+ email_details = []
521
+ for message in messages:
522
+ message_id = message['id']
523
+ message_url = f'https://gmail.googleapis.com/gmail/v1/users/me/messages/{message_id}'
524
+ message_response = await client.get(message_url, headers=headers)
525
+ message_response.raise_for_status()
526
+ message_data = message_response.json()
527
+
528
+ email_details.append({
529
+ "mailbox_email_id": message_data['id'],
530
+ "message_id": message_data['threadId'],
531
+ "email_subject": next((header['value'] for header in message_data['payload']['headers'] if header['name'] == 'Subject'), None),
532
+ "email_sender": next((header['value'] for header in message_data['payload']['headers'] if header['name'] == 'From'), None),
533
+ "email_recipients": [header['value'] for header in message_data['payload']['headers'] if header['name'] in ['To', 'Cc', 'Bcc']],
534
+ "email_date": next((header['value'] for header in message_data['payload']['headers'] if header['name'] == 'Date'), None),
535
+ "read_email_status": 'UNREAD' if 'UNREAD' in message_data['labelIds'] else 'READ',
536
+ "email_labels": message_data.get('labelIds', [])
537
+ })
538
+
539
+ return email_details
540
+
541
+ @assistant_tool
542
+ async def fetch_last_n_received_messages(sender_email: str, num_messages: int) -> List[Dict[str, Any]]:
543
+ """
544
+ Fetch the last n messages received from a specific sender using the Gmail API with a service account.
545
+ The service account must have domain-wide delegation to impersonate the recipient.
546
+
547
+ :param sender_email: The sender's email address.
548
+ :param num_messages: The number of recent messages to fetch.
549
+ :return: A list of email message details.
550
+ """
551
+ # Retrieve the service account JSON and email for automation from environment variables
552
+ service_account_base64 = os.getenv('GOOGLE_SERVICE_KEY')
553
+ automationemails = os.getenv('EMAIL_FOR_AUTOMATION')
554
+ if not service_account_base64 or not automationemails:
555
+ raise EnvironmentError("Required environment variables are not set.")
556
+
557
+ allowed_emails_for_automation = automationemails.split(",")
558
+ if not allowed_emails_for_automation:
559
+ raise EnvironmentError("No allowed emails for automation found in environment variables.")
560
+
561
+ mailbox_email = allowed_emails_for_automation[0]
562
+
563
+ # Function to convert base64-encoded JSON to a string
564
+ def convert_base_64_json(base64_json: str) -> str:
565
+ return base64.b64decode(base64_json).decode('utf-8')
566
+
567
+ service_account_json = convert_base_64_json(service_account_base64)
568
+
569
+ # Parse the JSON string into a dictionary
570
+ service_account_info = json.loads(service_account_json)
571
+
572
+ # Define the required scope for reading emails via Gmail API
573
+ SCOPES = ['https://mail.google.com/']
574
+
575
+ # Authenticate using the service account info and impersonate the email for automation
576
+ credentials = service_account.Credentials.from_service_account_info(
577
+ service_account_info, scopes=SCOPES
578
+ ).with_subject(mailbox_email)
579
+
580
+ # Refresh the token if necessary
581
+ if not credentials.valid:
582
+ request = Request()
583
+ credentials.refresh(request)
584
+
585
+ # Get the access token
586
+ access_token = credentials.token
587
+
588
+ # Define the Gmail API endpoint for listing messages
589
+ gmail_api_url = 'https://gmail.googleapis.com/gmail/v1/users/me/messages'
590
+
591
+ # Create the query parameters for the sender email
592
+ query = f'from:{sender_email}'
593
+
594
+ # Prepare the headers
595
+ headers = {
596
+ 'Authorization': f'Bearer {access_token}'
597
+ }
598
+
599
+ # Prepare the parameters
600
+ params = {
601
+ 'q': query,
602
+ 'maxResults': num_messages
603
+ }
604
+
605
+ async with httpx.AsyncClient() as client:
606
+ response = await client.get(gmail_api_url, headers=headers, params=params)
607
+ response.raise_for_status() # Raise an exception for HTTP errors
608
+ messages = response.json().get('messages', [])
609
+
610
+ email_details = []
611
+ for message in messages:
612
+ message_id = message['id']
613
+ message_url = f'https://gmail.googleapis.com/gmail/v1/users/me/messages/{message_id}'
614
+ message_response = await client.get(message_url, headers=headers)
615
+ message_response.raise_for_status()
616
+ message_data = message_response.json()
617
+
618
+ email_details.append({
619
+ "mailbox_email_id": message_data['id'],
620
+ "message_id": message_data['threadId'],
621
+ "email_subject": next((header['value'] for header in message_data['payload']['headers'] if header['name'] == 'Subject'), None),
622
+ "email_sender": next((header['value'] for header in message_data['payload']['headers'] if header['name'] == 'From'), None),
623
+ "email_recipients": [header['value'] for header in message_data['payload']['headers'] if header['name'] in ['To', 'Cc', 'Bcc']],
624
+ "email_date": next((header['value'] for header in message_data['payload']['headers'] if header['name'] == 'Date'), None),
625
+ "read_email_status": 'UNREAD' if 'UNREAD' in message_data['labelIds'] else 'READ',
626
+ "email_labels": message_data.get('labelIds', [])
627
+ })
628
+
629
+ return email_details
630
+
448
631
  @assistant_tool
449
632
  async def get_email_details_async(message_id: str, mailbox_email: str = "") -> Dict[str, Any]:
450
633
  """