@_vrsen/openswarm 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +152 -0
- package/bin/openswarm.js +38 -0
- package/config.py +34 -0
- package/data_analyst_agent/.cursor/rules/data_analyst.mdc +43 -0
- package/data_analyst_agent/__init__.py +3 -0
- package/data_analyst_agent/__pycache__/__init__.cpython-312.pyc +0 -0
- package/data_analyst_agent/__pycache__/data_analyst_agent.cpython-312.pyc +0 -0
- package/data_analyst_agent/data_analyst_agent.py +45 -0
- package/data_analyst_agent/instructions.md +173 -0
- package/data_analyst_agent/test_files/test_file.csv +21 -0
- package/data_analyst_agent/tools/__init__.py +6 -0
- package/deep_research/__init__.py +1 -0
- package/deep_research/__pycache__/__init__.cpython-312.pyc +0 -0
- package/deep_research/__pycache__/deep_research.cpython-312.pyc +0 -0
- package/deep_research/deep_research.py +27 -0
- package/deep_research/instructions.md +104 -0
- package/deep_research/tools/__init__.py +1 -0
- package/docs_agent/__init__.py +3 -0
- package/docs_agent/__pycache__/__init__.cpython-312.pyc +0 -0
- package/docs_agent/__pycache__/docs_agent.cpython-312.pyc +0 -0
- package/docs_agent/docs_agent.py +61 -0
- package/docs_agent/instructions.md +418 -0
- package/docs_agent/tools/ConvertDocument.py +323 -0
- package/docs_agent/tools/CreateDocument.py +287 -0
- package/docs_agent/tools/ListDocuments.py +134 -0
- package/docs_agent/tools/ModifyDocument.py +247 -0
- package/docs_agent/tools/RestoreDocument.py +79 -0
- package/docs_agent/tools/ViewDocument.py +153 -0
- package/docs_agent/tools/__init__.py +1 -0
- package/docs_agent/tools/__pycache__/ConvertDocument.cpython-312.pyc +0 -0
- package/docs_agent/tools/__pycache__/CreateDocument.cpython-312.pyc +0 -0
- package/docs_agent/tools/__pycache__/ListDocuments.cpython-312.pyc +0 -0
- package/docs_agent/tools/__pycache__/ModifyDocument.cpython-312.pyc +0 -0
- package/docs_agent/tools/__pycache__/RestoreDocument.cpython-312.pyc +0 -0
- package/docs_agent/tools/__pycache__/ViewDocument.cpython-312.pyc +0 -0
- package/docs_agent/tools/__pycache__/__init__.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__init__.py +1 -0
- package/docs_agent/tools/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/doc_file_utils.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_blocks.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_constants.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_core.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_css.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_images.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_page.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_paragraphs.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_playwright.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_selectors.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_docx_shared.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/__pycache__/html_validation.cpython-312.pyc +0 -0
- package/docs_agent/tools/utils/doc_file_utils.py +29 -0
- package/docs_agent/tools/utils/html_docx_blocks.py +262 -0
- package/docs_agent/tools/utils/html_docx_constants.py +78 -0
- package/docs_agent/tools/utils/html_docx_core.py +138 -0
- package/docs_agent/tools/utils/html_docx_css.py +262 -0
- package/docs_agent/tools/utils/html_docx_images.py +293 -0
- package/docs_agent/tools/utils/html_docx_page.py +185 -0
- package/docs_agent/tools/utils/html_docx_paragraphs.py +342 -0
- package/docs_agent/tools/utils/html_docx_playwright.py +184 -0
- package/docs_agent/tools/utils/html_docx_selectors.py +196 -0
- package/docs_agent/tools/utils/html_docx_shared.py +23 -0
- package/docs_agent/tools/utils/html_docx_tables.py +942 -0
- package/docs_agent/tools/utils/html_validation.py +102 -0
- package/helpers.py +59 -0
- package/image_generation_agent/__init__.py +1 -0
- package/image_generation_agent/__pycache__/__init__.cpython-312.pyc +0 -0
- package/image_generation_agent/__pycache__/image_generation_agent.cpython-312.pyc +0 -0
- package/image_generation_agent/image_generation_agent.py +31 -0
- package/image_generation_agent/instructions.md +80 -0
- package/image_generation_agent/tools/CombineImages.py +211 -0
- package/image_generation_agent/tools/EditImages.py +200 -0
- package/image_generation_agent/tools/GenerateImages.py +184 -0
- package/image_generation_agent/tools/RemoveBackground.py +108 -0
- package/image_generation_agent/tools/__init__.py +2 -0
- package/image_generation_agent/tools/__pycache__/CombineImages.cpython-312.pyc +0 -0
- package/image_generation_agent/tools/__pycache__/EditImages.cpython-312.pyc +0 -0
- package/image_generation_agent/tools/__pycache__/GenerateImages.cpython-312.pyc +0 -0
- package/image_generation_agent/tools/__pycache__/RemoveBackground.cpython-312.pyc +0 -0
- package/image_generation_agent/tools/utils/__init__.py +2 -0
- package/image_generation_agent/tools/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- package/image_generation_agent/tools/utils/__pycache__/image_io.cpython-312.pyc +0 -0
- package/image_generation_agent/tools/utils/image_io.py +308 -0
- package/onboard.py +325 -0
- package/orchestrator/__init__.py +3 -0
- package/orchestrator/__pycache__/__init__.cpython-312.pyc +0 -0
- package/orchestrator/__pycache__/orchestrator.cpython-312.pyc +0 -0
- package/orchestrator/instructions.md +90 -0
- package/orchestrator/orchestrator.py +33 -0
- package/package.json +49 -0
- package/patches/__init__.py +1 -0
- package/patches/__pycache__/__init__.cpython-312.pyc +0 -0
- package/patches/__pycache__/patch_agency_swarm_dual_comms.cpython-312.pyc +0 -0
- package/patches/__pycache__/patch_file_attachment_refs.cpython-312.pyc +0 -0
- package/patches/__pycache__/patch_ipython_interpreter_composio.cpython-312.pyc +0 -0
- package/patches/dom-to-pptx+1.1.5.patch +133440 -0
- package/patches/patch_agency_swarm_dual_comms.py +199 -0
- package/patches/patch_file_attachment_refs.py +74 -0
- package/patches/patch_ipython_interpreter_composio.py +54 -0
- package/pyproject.toml +67 -0
- package/run.py +343 -0
- package/server.py +26 -0
- package/shared_instructions.md +119 -0
- package/shared_tools/CopyFile.py +68 -0
- package/shared_tools/ExecuteTool.py +184 -0
- package/shared_tools/FindTools.py +101 -0
- package/shared_tools/ManageConnections.py +43 -0
- package/shared_tools/SearchTools.py +44 -0
- package/shared_tools/__init__.py +7 -0
- package/shared_tools/__pycache__/CopyFile.cpython-312.pyc +0 -0
- package/shared_tools/__pycache__/ExecuteTool.cpython-312.pyc +0 -0
- package/shared_tools/__pycache__/FindTools.cpython-312.pyc +0 -0
- package/shared_tools/__pycache__/ManageConnections.cpython-312.pyc +0 -0
- package/shared_tools/__pycache__/SearchTools.cpython-312.pyc +0 -0
- package/shared_tools/__pycache__/__init__.cpython-312.pyc +0 -0
- package/slides_agent/.cursor/rules/slides-agent-workflow.mdc +9 -0
- package/slides_agent/__init__.py +1 -0
- package/slides_agent/__pycache__/__init__.cpython-312.pyc +0 -0
- package/slides_agent/__pycache__/slides_agent.cpython-312.pyc +0 -0
- package/slides_agent/instructions.md +298 -0
- package/slides_agent/pptx/SKILL.md +528 -0
- package/slides_agent/pptx/html2pptx.md +625 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/slides_agent/pptx/ooxml/schemas/mce/mc.xsd +75 -0
- package/slides_agent/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/slides_agent/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/slides_agent/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/slides_agent/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/slides_agent/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/slides_agent/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/slides_agent/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/slides_agent/pptx/ooxml/scripts/pack.py +169 -0
- package/slides_agent/pptx/ooxml/scripts/unpack.py +29 -0
- package/slides_agent/pptx/ooxml/scripts/validate.py +69 -0
- package/slides_agent/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/slides_agent/pptx/ooxml/scripts/validation/base.py +951 -0
- package/slides_agent/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/slides_agent/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/slides_agent/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/slides_agent/pptx/ooxml.md +427 -0
- package/slides_agent/pptx/scripts/html2pptx.js +1092 -0
- package/slides_agent/pptx/scripts/inventory.py +1020 -0
- package/slides_agent/pptx/scripts/rearrange.py +231 -0
- package/slides_agent/pptx/scripts/replace.py +385 -0
- package/slides_agent/pptx/scripts/thumbnail.py +451 -0
- package/slides_agent/slides_agent.py +109 -0
- package/slides_agent/test_deck/_theme.css +92 -0
- package/slides_agent/test_deck/assets/placeholder.svg +11 -0
- package/slides_agent/test_deck/slide_01_title.html +10 -0
- package/slides_agent/test_deck/slide_02_image_split.html +23 -0
- package/slides_agent/test_deck/slide_03_kpi.html +21 -0
- package/slides_agent/tools/ApplyPptxTextReplacements.py +91 -0
- package/slides_agent/tools/BuildPptxFromHtmlSlides.py +221 -0
- package/slides_agent/tools/CheckSlide.py +218 -0
- package/slides_agent/tools/CheckSlideCanvasOverflow.py +221 -0
- package/slides_agent/tools/CreateImageMontage.py +261 -0
- package/slides_agent/tools/CreatePptxThumbnailGrid.py +168 -0
- package/slides_agent/tools/DeleteSlide.py +78 -0
- package/slides_agent/tools/DownloadImage.py +79 -0
- package/slides_agent/tools/EnsureRasterImage.py +157 -0
- package/slides_agent/tools/ExtractPptxTextInventory.py +104 -0
- package/slides_agent/tools/GenerateImage.py +189 -0
- package/slides_agent/tools/ImageSearch.py +127 -0
- package/slides_agent/tools/InsertNewSlides.py +393 -0
- package/slides_agent/tools/ManageTheme.py +112 -0
- package/slides_agent/tools/ModifySlide.py +563 -0
- package/slides_agent/tools/ReadSlide.py +26 -0
- package/slides_agent/tools/RearrangePptxSlidesFromTemplate.py +114 -0
- package/slides_agent/tools/RestoreSnapshot.py +89 -0
- package/slides_agent/tools/SlideScreenshot.py +66 -0
- package/slides_agent/tools/__init__.py +54 -0
- package/slides_agent/tools/__pycache__/ApplyPptxTextReplacements.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/BuildPptxFromHtmlSlides.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/CheckSlide.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/CheckSlideCanvasOverflow.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/CreateImageMontage.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/CreatePptxThumbnailGrid.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/DeleteSlide.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/DownloadImage.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/EnsureRasterImage.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/ExtractPptxTextInventory.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/GenerateImage.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/ImageSearch.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/InsertNewSlides.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/ManageTheme.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/ModifySlide.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/ReadSlide.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/RearrangePptxSlidesFromTemplate.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/RestoreSnapshot.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/SlideScreenshot.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/__init__.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/slide_file_utils.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/slide_html_utils.cpython-312.pyc +0 -0
- package/slides_agent/tools/__pycache__/template_registry.cpython-312.pyc +0 -0
- package/slides_agent/tools/deck_utils.py +31 -0
- package/slides_agent/tools/html2pptx_runner.js +1183 -0
- package/slides_agent/tools/html_writer_instructions.md +149 -0
- package/slides_agent/tools/slide_file_utils.py +108 -0
- package/slides_agent/tools/slide_html_utils.py +354 -0
- package/slides_agent/tools/template_registry.py +55 -0
- package/swarm.py +82 -0
- package/video_generation_agent/__init__.py +1 -0
- package/video_generation_agent/__pycache__/__init__.cpython-312.pyc +0 -0
- package/video_generation_agent/__pycache__/video_generation_agent.cpython-312.pyc +0 -0
- package/video_generation_agent/instructions.md +178 -0
- package/video_generation_agent/tools/AddSubtitles.py +425 -0
- package/video_generation_agent/tools/CombineImages.py +166 -0
- package/video_generation_agent/tools/CombineVideos.py +113 -0
- package/video_generation_agent/tools/EditAudio.py +297 -0
- package/video_generation_agent/tools/EditImage.py +144 -0
- package/video_generation_agent/tools/EditVideoContent.py +369 -0
- package/video_generation_agent/tools/GenerateImage.py +133 -0
- package/video_generation_agent/tools/GenerateVideo.py +556 -0
- package/video_generation_agent/tools/TrimVideo.py +233 -0
- package/video_generation_agent/tools/__init__.py +1 -0
- package/video_generation_agent/tools/__pycache__/AddSubtitles.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/CombineImages.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/CombineVideos.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/EditAudio.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/EditImage.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/EditVideoContent.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/GenerateImage.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/GenerateVideo.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/__pycache__/TrimVideo.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/utils/__init__.py +1 -0
- package/video_generation_agent/tools/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/utils/__pycache__/image_utils.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/utils/__pycache__/video_utils.cpython-312.pyc +0 -0
- package/video_generation_agent/tools/utils/image_utils.py +174 -0
- package/video_generation_agent/tools/utils/video_utils.py +522 -0
- package/video_generation_agent/video_generation_agent.py +26 -0
- package/virtual_assistant/__init__.py +1 -0
- package/virtual_assistant/__pycache__/__init__.cpython-312.pyc +0 -0
- package/virtual_assistant/__pycache__/virtual_assistant.cpython-312.pyc +0 -0
- package/virtual_assistant/instructions.md +206 -0
- package/virtual_assistant/tools/AddLabelToEmail.py +154 -0
- package/virtual_assistant/tools/CheckEventsForDate.py +218 -0
- package/virtual_assistant/tools/CheckUnreadSlackMessages.py +216 -0
- package/virtual_assistant/tools/CreateCalendarEvent.py +261 -0
- package/virtual_assistant/tools/DeleteCalendarEvent.py +137 -0
- package/virtual_assistant/tools/DeleteDraft.py +95 -0
- package/virtual_assistant/tools/DraftEmail.py +239 -0
- package/virtual_assistant/tools/EditFile.py +113 -0
- package/virtual_assistant/tools/FindEmails.py +330 -0
- package/virtual_assistant/tools/GetCurrentTime.py +69 -0
- package/virtual_assistant/tools/GetSlackUserInfo.py +117 -0
- package/virtual_assistant/tools/ListDirectory.py +113 -0
- package/virtual_assistant/tools/ListSkills.py +94 -0
- package/virtual_assistant/tools/ManageLabels.py +295 -0
- package/virtual_assistant/tools/ProductSearch.py +254 -0
- package/virtual_assistant/tools/ReadEmail.py +251 -0
- package/virtual_assistant/tools/ReadFile.py +108 -0
- package/virtual_assistant/tools/ReadSlackMessages.py +191 -0
- package/virtual_assistant/tools/RemoveLabelFromEmail.py +137 -0
- package/virtual_assistant/tools/RescheduleCalendarEvent.py +227 -0
- package/virtual_assistant/tools/ScholarSearch.py +216 -0
- package/virtual_assistant/tools/SendDraft.py +101 -0
- package/virtual_assistant/tools/SendSlackMessage.py +148 -0
- package/virtual_assistant/tools/WriteFile.py +95 -0
- package/virtual_assistant/tools/__init__.py +1 -0
- package/virtual_assistant/tools/__pycache__/AddLabelToEmail.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/CheckEventsForDate.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/CheckUnreadSlackMessages.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/CreateCalendarEvent.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/DeleteCalendarEvent.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/DeleteDraft.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/DraftEmail.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/EditFile.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/FindEmails.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/GetCurrentTime.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/GetSlackUserInfo.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ListDirectory.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ListSkills.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ManageLabels.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ProductSearch.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ReadEmail.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ReadFile.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ReadSlackMessages.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/RemoveLabelFromEmail.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/RescheduleCalendarEvent.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/ScholarSearch.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/SendDraft.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/SendSlackMessage.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/WriteFile.cpython-312.pyc +0 -0
- package/virtual_assistant/tools/__pycache__/__init__.cpython-312.pyc +0 -0
- package/virtual_assistant/virtual_assistant.py +52 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Your Role
|
|
2
|
+
|
|
3
|
+
You are an elite executive assistant for busy business owners and entrepreneurs. Your main goal is to save the user as much time as possible by handling administrative tasks.
|
|
4
|
+
|
|
5
|
+
# North Star Principles
|
|
6
|
+
|
|
7
|
+
1. **Protect the User's Time:** Filter requests and prioritize what matters most.
|
|
8
|
+
2. **Efficiency:** Be clear, committed, and always include context.
|
|
9
|
+
3. **Responsive:** Every request deserves a clear, timely response.
|
|
10
|
+
4. **Read the Play:** Be preemptive. Anticipate needs before they're stated.
|
|
11
|
+
5. **Prioritize Revenue:** Order tasks based on what generates the biggest outcome.
|
|
12
|
+
6. **Capture Preferences:** Questions should only be asked once. Remember and reference for the future.
|
|
13
|
+
|
|
14
|
+
# Communication Flows
|
|
15
|
+
|
|
16
|
+
- **Handoff to Deep Research:** For comprehensive research tasks (market analysis, competitor research, literature reviews, background investigation)
|
|
17
|
+
- **Handoff to Data Analyst:** For data analysis tasks (metrics, revenue analysis, dashboards, KPIs, visualizations, business intelligence)
|
|
18
|
+
|
|
19
|
+
Handle general administrative tasks (email, calendar, messaging, documents) yourself.
|
|
20
|
+
|
|
21
|
+
# Primary Workflow
|
|
22
|
+
|
|
23
|
+
Follow this general process for all tasks:
|
|
24
|
+
|
|
25
|
+
## 1. Gather Context
|
|
26
|
+
|
|
27
|
+
For tasks that are not straightforward and require multiple tool calls:
|
|
28
|
+
|
|
29
|
+
1. **Ask clarifying questions** before taking action
|
|
30
|
+
2. Understand the full scope: Who, What, Where, When, Why, How
|
|
31
|
+
3. Confirm preferences (timing, format, recipients, etc.)
|
|
32
|
+
4. Research other available sources, if applicable. (For example, previous email threads, relevant documents, web searches, etc.)
|
|
33
|
+
|
|
34
|
+
Skip this step only for simple, single-action tasks with clear instructions.
|
|
35
|
+
|
|
36
|
+
Only ask the most **essential** questions. Avoid burdening the user with too many questions.
|
|
37
|
+
|
|
38
|
+
## 2. Connect to External Systems
|
|
39
|
+
|
|
40
|
+
When the task requires external systems (email, calendar, CRM, messaging, etc.), follow this sequence:
|
|
41
|
+
|
|
42
|
+
### 2.1 Check Existing Connections
|
|
43
|
+
|
|
44
|
+
**Always start here.** Use `ManageConnections` to see what systems are already connected.
|
|
45
|
+
|
|
46
|
+
### 2.2 If System is NOT Connected
|
|
47
|
+
|
|
48
|
+
1. If the user didn't specify which system (e.g., "send an email" without saying Gmail/Outlook):
|
|
49
|
+
- Check what's already connected and infer from that
|
|
50
|
+
- If only one relevant system is connected (e.g., only Gmail for email), use it
|
|
51
|
+
- If none connected, ask which system they prefer
|
|
52
|
+
2. Use `SearchTools` to find the relevant tools (e.g., `query="send email"`, `toolkit="GMAIL"`)
|
|
53
|
+
3. Generate authentication link and provide it to the user
|
|
54
|
+
4. Wait for the user to complete authentication
|
|
55
|
+
5. Once connected, proceed to step 3
|
|
56
|
+
|
|
57
|
+
## 3. Execute Tools
|
|
58
|
+
|
|
59
|
+
**Priority Order:** Always prefer specialized tools over generic Composio tools.
|
|
60
|
+
|
|
61
|
+
### Priority 1: Specialized Tools (Highest Preference)
|
|
62
|
+
|
|
63
|
+
Use the available tools like `FindEmails`, `ReadEmail`, `DraftEmail`, `SendDraft`, `CheckEventsForDate`, `CreateCalendarEvent`, `RescheduleCalendarEvent`, `DeleteCalendarEvent`, `ProductSearch`, `ScholarSearch`, etc. when they match the task. They are optimized, tested, and handle edge cases.
|
|
64
|
+
|
|
65
|
+
**Example workflow:**
|
|
66
|
+
|
|
67
|
+
1. User: "Check my unread emails"
|
|
68
|
+
2. `ManageConnections` → Gmail is connected
|
|
69
|
+
3. `CheckUnreadEmails(provider="gmail", limit=10)` → Done!
|
|
70
|
+
|
|
71
|
+
### Priority 2: Composio Tools (Fallback)
|
|
72
|
+
|
|
73
|
+
Use `FindTools` + `ExecuteTool` only when no specialized tool exists for the task.
|
|
74
|
+
|
|
75
|
+
1. Use `FindTools` with `include_args=True` to get the exact tool names and parameters
|
|
76
|
+
|
|
77
|
+
- Example: `tool_names=["GMAIL_SEND_MESSAGE"], include_args=True`
|
|
78
|
+
- Only load parameters for tools you're about to execute
|
|
79
|
+
|
|
80
|
+
2. Choose the right execution method:
|
|
81
|
+
|
|
82
|
+
#### Option A: ExecuteTool (for simple tasks)
|
|
83
|
+
|
|
84
|
+
Use `ExecuteTool` for single tool execution without data transformation. Optionally filter output with `return_fields`.
|
|
85
|
+
|
|
86
|
+
#### Option B: ProgrammaticToolCalling (for complex workflows)
|
|
87
|
+
|
|
88
|
+
Use this option for tasks that require multiple tool calls, data processing, storing intermediate results, or complex logic.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from helpers import composio, user_id # only need to be imported in the first tool call
|
|
92
|
+
|
|
93
|
+
result = composio.tools.execute(
|
|
94
|
+
"TOOL_NAME_HERE",
|
|
95
|
+
user_id=user_id,
|
|
96
|
+
arguments={"param1": "value1", "param2": "value2"},
|
|
97
|
+
dangerously_skip_version_check=True
|
|
98
|
+
)
|
|
99
|
+
print(result)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Examples of tasks suitable for Option B:
|
|
103
|
+
|
|
104
|
+
- Processing or analyzing data from Google Sheets
|
|
105
|
+
- Bulk operations (e.g., labeling multiple emails based on criteria)
|
|
106
|
+
- Cross-system workflows (e.g., create calendar event from email data)
|
|
107
|
+
- Tasks requiring loops or conditional logic
|
|
108
|
+
- Aggregating data from multiple API calls
|
|
109
|
+
|
|
110
|
+
**Example workflow (when no specialized tool exists):**
|
|
111
|
+
|
|
112
|
+
1. `ManageConnections` → see Slack is connected
|
|
113
|
+
2. `FindTools(toolkit="SLACK", include_args=False)` → discover SLACK_SEND_MESSAGE exists
|
|
114
|
+
3. `FindTools(tool_names=["SLACK_SEND_MESSAGE"], include_args=True)` → get parameters
|
|
115
|
+
4. Choose execution:
|
|
116
|
+
- Simple task → `ExecuteTool`
|
|
117
|
+
- Complex task → `ProgrammaticToolCalling`
|
|
118
|
+
|
|
119
|
+
### 4. Common Composio Toolkits (for Priority 2 fallback)
|
|
120
|
+
|
|
121
|
+
Use these toolkits with `FindTools` when no specialized tool covers your task:
|
|
122
|
+
|
|
123
|
+
- **Email:** GMAIL, OUTLOOK
|
|
124
|
+
- **Calendar/Scheduling:** GOOGLECALENDAR, OUTLOOK, CALENDLY
|
|
125
|
+
- **Video/Meetings:** ZOOM, GOOGLEMEET, MICROSOFT_TEAMS
|
|
126
|
+
- **Messaging:** SLACK, WHATSAPP, TELEGRAM, DISCORD
|
|
127
|
+
- **Documents/Notes:** GOOGLEDOCS, GOOGLESHEETS, NOTION, AIRTABLE, CODA
|
|
128
|
+
- **Storage:** GOOGLEDRIVE, DROPBOX
|
|
129
|
+
- **Project Management:** NOTION, JIRA, ASANA, TRELLO, CLICKUP, MONDAY, BASECAMP
|
|
130
|
+
- **CRM/Sales:** HUBSPOT, SALESFORCE, PIPEDRIVE, APOLLO
|
|
131
|
+
- **Payments/Accounting:** STRIPE, SQUARE, QUICKBOOKS, XERO, FRESHBOOKS
|
|
132
|
+
- **Customer Support:** ZENDESK, INTERCOM, FRESHDESK
|
|
133
|
+
- **Marketing/Email:** MAILCHIMP, SENDGRID
|
|
134
|
+
- **Social Media:** LINKEDIN, TWITTER, INSTAGRAM
|
|
135
|
+
- **E-commerce:** SHOPIFY
|
|
136
|
+
- **Signatures:** DOCUSIGN
|
|
137
|
+
- **Design/Collaboration:** FIGMA, CANVA, MIRO
|
|
138
|
+
- **Development:** GITHUB
|
|
139
|
+
- **Analytics:** AMPLITUDE, MIXPANEL, SEGMENT
|
|
140
|
+
|
|
141
|
+
### 5. Best Practices
|
|
142
|
+
|
|
143
|
+
- **Save intermediate results to a variable**: Avoid fetching the same data multiple times.
|
|
144
|
+
- **Explore the data**: Before filtering or extracting data, first explore the structure (database schema, email labels, folder organization, etc.) to understand what's available and find the most efficient query approach.
|
|
145
|
+
- **Format tool outputs**: Before logging a tool's output, check what fields and data format it returns. Extract and log only the information you need from the response.
|
|
146
|
+
|
|
147
|
+
## 3. Plan Your Approach
|
|
148
|
+
|
|
149
|
+
Before executing any tools:
|
|
150
|
+
|
|
151
|
+
1. **Think through the complete task** end-to-end
|
|
152
|
+
2. **Identify all required steps** in sequence
|
|
153
|
+
3. **Anticipate potential issues** or edge cases
|
|
154
|
+
4. **Determine if any steps are irreversible** (sending emails, deleting records, making purchases)
|
|
155
|
+
|
|
156
|
+
## 4. Execute with Minimal Tool Calls
|
|
157
|
+
|
|
158
|
+
1. Execute the planned steps efficiently
|
|
159
|
+
2. Use the fewest tool calls necessary
|
|
160
|
+
3. Handle errors gracefully and debug if needed
|
|
161
|
+
4. **For destructive/irreversible actions:**
|
|
162
|
+
- **Default behavior:** Always confirm before executing
|
|
163
|
+
- **Pre-authorized actions:** If the user explicitly includes words like "send immediately", "delete now", or "book it", you may skip confirmation
|
|
164
|
+
- **Email workflow:**
|
|
165
|
+
- Create draft in the email system (Gmail, Outlook, etc.)
|
|
166
|
+
- If preview link is available: provide the link for review
|
|
167
|
+
- If no preview link: output the full draft content in chat for review
|
|
168
|
+
- Wait for approval → then send (unless pre-authorized)
|
|
169
|
+
- **CRM deletions:** Show record link → confirm deletion → execute (unless pre-authorized)
|
|
170
|
+
- **Purchases:** Show details/cost → wait for approval → execute (unless pre-authorized)
|
|
171
|
+
- **Same-day calendar changes:** Notify immediately → confirm → execute
|
|
172
|
+
- **Never output IDs without context:** Don't show message IDs, record IDs, or other technical identifiers unless they're part of a clickable link
|
|
173
|
+
|
|
174
|
+
## 5. Report and Suggest Next Steps
|
|
175
|
+
|
|
176
|
+
1. Summarize what was done
|
|
177
|
+
2. Show key results or outcomes
|
|
178
|
+
3. Proactively suggest logical next steps
|
|
179
|
+
|
|
180
|
+
# Output Format
|
|
181
|
+
|
|
182
|
+
- Respond concisely using simple, easy to read language.
|
|
183
|
+
- Use bullet points and clear formatting for readability.
|
|
184
|
+
- When executing tasks, report: what was done, the result, and any next steps.
|
|
185
|
+
- When drafting messages directly in chat (like for WhatsApp or any other unsupported messaging system), output the full message content and nothing else so the user can just copy it.
|
|
186
|
+
- Be proactive in suggesting the next steps.
|
|
187
|
+
- NEVER use em dashes.
|
|
188
|
+
- If you are stuck / blocked on a specific task, use the **1-3-1 technique**:
|
|
189
|
+
1. Clearly define the problem.
|
|
190
|
+
2. Identify 3 possible solutions.
|
|
191
|
+
3. Provide your recommendation on how to proceed among the 3 options.
|
|
192
|
+
- When responding on behalf of the user via email, always be polite and professional.
|
|
193
|
+
- When responding on behalf of the user via messaging (WhatsApp, Slack, etc.), be more casual and friendly. Do not include subjects and signatures unless requested in draft messages.
|
|
194
|
+
- For slack messages, use Slack formatting: _bold_, _italic_, ~strike~, `inline code` and `code blocks`, > quotes, simple lists, emoji (:smile:), links as auto URLs or `<https://example.com|label>` (also `[label](url)` in markup mode), plus mentions like `<@USERID>` and `<#CHANNELID>`
|
|
195
|
+
|
|
196
|
+
# Additional Notes
|
|
197
|
+
|
|
198
|
+
- **Context window efficiency:** Only log what you actually need to see. Context window is a public good.
|
|
199
|
+
- **Confirmation vs speed:** Default to asking confirmation for irreversible operations, but skip if the user pre-authorizes with explicit language ("send now", "book immediately", etc.)
|
|
200
|
+
- **Preview workflow:**
|
|
201
|
+
- First, try to create drafts in the external system (Gmail, Notion, etc.) and provide preview links
|
|
202
|
+
- If preview links aren't available, output the full content in chat for review
|
|
203
|
+
- For local files created during execution, include the file path in your response
|
|
204
|
+
- Never show technical IDs (message IDs, record IDs) without providing either a link or the actual content
|
|
205
|
+
- Do not put preview links inside a code block so the user can click on them.
|
|
206
|
+
- **Remember preferences:** Once the user tells you their preference (which email system, which calendar, meeting length, etc.), remember it for future tasks.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from typing import Literal, List
|
|
2
|
+
from agency_swarm.tools import BaseTool
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
from helpers import execute_composio_tool
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AddLabelToEmail(BaseTool):
|
|
10
|
+
"""
|
|
11
|
+
Adds labels to a specific email message.
|
|
12
|
+
|
|
13
|
+
For Gmail: Use label IDs (system labels like 'STARRED', 'IMPORTANT', 'INBOX',
|
|
14
|
+
or custom label IDs like 'Label_123' from ManageLabels).
|
|
15
|
+
|
|
16
|
+
For Outlook: Use category names (must exist in the user's category list).
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
provider: Literal["gmail", "outlook"] = Field(
|
|
20
|
+
...,
|
|
21
|
+
description="Email provider: 'gmail' or 'outlook'"
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
message_id: str = Field(
|
|
25
|
+
...,
|
|
26
|
+
description="The message ID to add labels to (obtained from CheckUnreadEmails)"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
label_ids: List[str] = Field(
|
|
30
|
+
...,
|
|
31
|
+
description="List of label IDs to add. Gmail: 'STARRED', 'IMPORTANT', 'Label_123'. Outlook: category names."
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def run(self):
|
|
35
|
+
try:
|
|
36
|
+
if self.provider == "gmail":
|
|
37
|
+
return self._add_gmail_labels(execute_composio_tool)
|
|
38
|
+
else:
|
|
39
|
+
return self._add_outlook_categories(execute_composio_tool)
|
|
40
|
+
|
|
41
|
+
except Exception as e:
|
|
42
|
+
return f"Error adding labels: {str(e)}"
|
|
43
|
+
|
|
44
|
+
def _add_gmail_labels(self, execute_tool) -> str:
|
|
45
|
+
"""Adds labels to a Gmail message."""
|
|
46
|
+
result = execute_tool(
|
|
47
|
+
tool_name="GMAIL_ADD_LABEL_TO_EMAIL",
|
|
48
|
+
arguments={
|
|
49
|
+
"user_id": "me",
|
|
50
|
+
"message_id": self.message_id,
|
|
51
|
+
"add_label_ids": self.label_ids
|
|
52
|
+
},
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if isinstance(result, dict) and result.get("error"):
|
|
56
|
+
return f"Error adding Gmail labels: {result.get('error')}"
|
|
57
|
+
|
|
58
|
+
data = result.get("data", {})
|
|
59
|
+
|
|
60
|
+
return json.dumps({
|
|
61
|
+
"provider": "gmail",
|
|
62
|
+
"success": True,
|
|
63
|
+
"message_id": self.message_id,
|
|
64
|
+
"labels_added": self.label_ids,
|
|
65
|
+
"current_labels": data.get("labelIds", [])
|
|
66
|
+
}, indent=2)
|
|
67
|
+
|
|
68
|
+
def _add_outlook_categories(self, execute_tool) -> str:
|
|
69
|
+
"""Adds categories to an Outlook message."""
|
|
70
|
+
# For Outlook, we need to update the message with categories
|
|
71
|
+
# First get current categories, then add new ones
|
|
72
|
+
|
|
73
|
+
# Get current message
|
|
74
|
+
get_result = execute_tool(
|
|
75
|
+
tool_name="OUTLOOK_GET_MESSAGE",
|
|
76
|
+
arguments={
|
|
77
|
+
"user_id": "me",
|
|
78
|
+
"message_id": self.message_id,
|
|
79
|
+
"select": ["id", "categories"]
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if isinstance(get_result, dict) and get_result.get("error"):
|
|
84
|
+
return f"Error getting Outlook message: {get_result.get('error')}"
|
|
85
|
+
|
|
86
|
+
current_categories = get_result.get("data", {}).get("categories", [])
|
|
87
|
+
|
|
88
|
+
# Combine current and new categories (avoid duplicates)
|
|
89
|
+
updated_categories = list(set(current_categories + self.label_ids))
|
|
90
|
+
|
|
91
|
+
# Update the message with new categories
|
|
92
|
+
# Note: Outlook doesn't have a direct "add category" API, need to use update
|
|
93
|
+
return json.dumps({
|
|
94
|
+
"provider": "outlook",
|
|
95
|
+
"success": True,
|
|
96
|
+
"message_id": self.message_id,
|
|
97
|
+
"categories_added": self.label_ids,
|
|
98
|
+
"current_categories": current_categories,
|
|
99
|
+
"updated_categories": updated_categories,
|
|
100
|
+
"note": "Outlook category update requires OUTLOOK_UPDATE_MESSAGE which may not be available"
|
|
101
|
+
}, indent=2)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
if __name__ == "__main__":
|
|
105
|
+
import sys
|
|
106
|
+
import os
|
|
107
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
|
|
108
|
+
|
|
109
|
+
print("=" * 60)
|
|
110
|
+
print("AddLabelToEmail Test Suite")
|
|
111
|
+
print("=" * 60)
|
|
112
|
+
print()
|
|
113
|
+
|
|
114
|
+
# Get a message ID first
|
|
115
|
+
from virtual_assistant.tools.CheckUnreadEmails import CheckUnreadEmails
|
|
116
|
+
check_tool = CheckUnreadEmails(provider="gmail", limit=1)
|
|
117
|
+
result = check_tool.run()
|
|
118
|
+
|
|
119
|
+
import json
|
|
120
|
+
data = json.loads(result)
|
|
121
|
+
if data.get("emails"):
|
|
122
|
+
message_id = data["emails"][0]["message_id"]
|
|
123
|
+
|
|
124
|
+
# Test: Add STARRED label
|
|
125
|
+
print("Test: Add STARRED label to email")
|
|
126
|
+
print("-" * 60)
|
|
127
|
+
tool = AddLabelToEmail(
|
|
128
|
+
provider="gmail",
|
|
129
|
+
message_id=message_id,
|
|
130
|
+
label_ids=["STARRED"]
|
|
131
|
+
)
|
|
132
|
+
result = tool.run()
|
|
133
|
+
print(result)
|
|
134
|
+
print()
|
|
135
|
+
|
|
136
|
+
# Remove it to clean up
|
|
137
|
+
from virtual_assistant.tools.RemoveLabelFromEmail import RemoveLabelFromEmail
|
|
138
|
+
print("Cleanup: Remove STARRED label")
|
|
139
|
+
print("-" * 60)
|
|
140
|
+
tool = RemoveLabelFromEmail(
|
|
141
|
+
provider="gmail",
|
|
142
|
+
message_id=message_id,
|
|
143
|
+
label_ids=["STARRED"]
|
|
144
|
+
)
|
|
145
|
+
result = tool.run()
|
|
146
|
+
print(result)
|
|
147
|
+
else:
|
|
148
|
+
print("No emails to test with")
|
|
149
|
+
|
|
150
|
+
print()
|
|
151
|
+
print("=" * 60)
|
|
152
|
+
print("Tests completed!")
|
|
153
|
+
print("=" * 60)
|
|
154
|
+
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
from typing import Literal
|
|
2
|
+
from agency_swarm.tools import BaseTool
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
import json
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
from helpers import execute_composio_tool
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class CheckEventsForDate(BaseTool):
|
|
11
|
+
"""
|
|
12
|
+
Retrieves all calendar events for a specific date (Google Calendar or Outlook).
|
|
13
|
+
|
|
14
|
+
Returns event details including title, start/end times, and event IDs.
|
|
15
|
+
Events are returned in chronological order by start time.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
provider: Literal["google", "outlook"] = Field(
|
|
19
|
+
...,
|
|
20
|
+
description="Calendar provider to use: 'google' (Google Calendar) or 'outlook'"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
date: str = Field(
|
|
24
|
+
...,
|
|
25
|
+
description="Date to check for events in YYYY-MM-DD format (e.g., '2026-01-07')"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
timezone: str = Field(
|
|
29
|
+
default="UTC",
|
|
30
|
+
description="Timezone for the date and event times. Use IANA format (e.g., 'America/New_York', 'Europe/London', 'Asia/Dubai')"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def run(self):
|
|
34
|
+
try:
|
|
35
|
+
try:
|
|
36
|
+
parsed_date = datetime.strptime(self.date, "%Y-%m-%d")
|
|
37
|
+
except ValueError:
|
|
38
|
+
return f"Error: Invalid date format '{self.date}'. Use YYYY-MM-DD format."
|
|
39
|
+
|
|
40
|
+
if self.provider == "google":
|
|
41
|
+
return self._fetch_google_calendar_events(execute_composio_tool, parsed_date)
|
|
42
|
+
else:
|
|
43
|
+
return self._fetch_outlook_events(execute_composio_tool, parsed_date)
|
|
44
|
+
|
|
45
|
+
except Exception as e:
|
|
46
|
+
return f"Error fetching calendar events: {str(e)}"
|
|
47
|
+
|
|
48
|
+
def _fetch_google_calendar_events(self, execute_tool, date: datetime) -> str:
|
|
49
|
+
"""Fetches events from Google Calendar for the specified date."""
|
|
50
|
+
time_min = f"{date.strftime('%Y-%m-%d')}T00:00:00Z"
|
|
51
|
+
time_max = f"{date.strftime('%Y-%m-%d')}T23:59:59Z"
|
|
52
|
+
|
|
53
|
+
result = execute_tool(
|
|
54
|
+
tool_name="GOOGLECALENDAR_EVENTS_LIST",
|
|
55
|
+
arguments={
|
|
56
|
+
"calendarId": "primary",
|
|
57
|
+
"timeMin": time_min,
|
|
58
|
+
"timeMax": time_max,
|
|
59
|
+
"singleEvents": True,
|
|
60
|
+
"orderBy": "startTime",
|
|
61
|
+
"timeZone": self.timezone
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
if isinstance(result, dict) and result.get("error"):
|
|
66
|
+
return f"Error fetching Google Calendar events: {result.get('error')}"
|
|
67
|
+
|
|
68
|
+
events = result.get("data", {}).get("items", [])
|
|
69
|
+
|
|
70
|
+
if not events:
|
|
71
|
+
return json.dumps({
|
|
72
|
+
"provider": "google",
|
|
73
|
+
"date": self.date,
|
|
74
|
+
"timezone": self.timezone,
|
|
75
|
+
"count": 0,
|
|
76
|
+
"events": []
|
|
77
|
+
}, indent=2)
|
|
78
|
+
|
|
79
|
+
formatted_events = []
|
|
80
|
+
for event in events:
|
|
81
|
+
start = event.get("start", {})
|
|
82
|
+
end = event.get("end", {})
|
|
83
|
+
|
|
84
|
+
# Handle all-day events (have 'date') vs timed events (have 'dateTime')
|
|
85
|
+
start_time = start.get("dateTime") or start.get("date", "")
|
|
86
|
+
end_time = end.get("dateTime") or end.get("date", "")
|
|
87
|
+
is_all_day = "date" in start and "dateTime" not in start
|
|
88
|
+
|
|
89
|
+
formatted_events.append({
|
|
90
|
+
"title": event.get("summary", "(No title)"),
|
|
91
|
+
"event_id": event.get("id"),
|
|
92
|
+
"start": start_time,
|
|
93
|
+
"end": end_time,
|
|
94
|
+
"all_day": is_all_day,
|
|
95
|
+
"description": event.get("description", ""),
|
|
96
|
+
"location": event.get("location", ""),
|
|
97
|
+
"status": event.get("status", ""),
|
|
98
|
+
"html_link": event.get("htmlLink", "")
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
return json.dumps({
|
|
102
|
+
"provider": "google",
|
|
103
|
+
"date": self.date,
|
|
104
|
+
"timezone": self.timezone,
|
|
105
|
+
"count": len(formatted_events),
|
|
106
|
+
"events": formatted_events
|
|
107
|
+
}, indent=2)
|
|
108
|
+
|
|
109
|
+
def _fetch_outlook_events(self, execute_tool, date: datetime) -> str:
|
|
110
|
+
"""Fetches events from Outlook Calendar for the specified date."""
|
|
111
|
+
start_datetime = f"{date.strftime('%Y-%m-%d')}T00:00:00Z"
|
|
112
|
+
end_datetime = f"{date.strftime('%Y-%m-%d')}T23:59:59Z"
|
|
113
|
+
|
|
114
|
+
result = execute_tool(
|
|
115
|
+
tool_name="OUTLOOK_GET_CALENDAR_VIEW",
|
|
116
|
+
arguments={
|
|
117
|
+
"user_id": "me",
|
|
118
|
+
"start_datetime": start_datetime,
|
|
119
|
+
"end_datetime": end_datetime,
|
|
120
|
+
"timezone": self.timezone,
|
|
121
|
+
"top": 100
|
|
122
|
+
},
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if isinstance(result, dict) and result.get("error"):
|
|
126
|
+
return f"Error fetching Outlook events: {result.get('error')}"
|
|
127
|
+
|
|
128
|
+
events = result.get("data", {}).get("value", [])
|
|
129
|
+
|
|
130
|
+
if not events:
|
|
131
|
+
return json.dumps({
|
|
132
|
+
"provider": "outlook",
|
|
133
|
+
"date": self.date,
|
|
134
|
+
"timezone": self.timezone,
|
|
135
|
+
"count": 0,
|
|
136
|
+
"events": []
|
|
137
|
+
}, indent=2)
|
|
138
|
+
|
|
139
|
+
formatted_events = []
|
|
140
|
+
for event in events:
|
|
141
|
+
start = event.get("start", {})
|
|
142
|
+
end = event.get("end", {})
|
|
143
|
+
|
|
144
|
+
# Extract body/description content
|
|
145
|
+
body_data = event.get("body", {})
|
|
146
|
+
description = body_data.get("content", "") if isinstance(body_data, dict) else ""
|
|
147
|
+
|
|
148
|
+
formatted_events.append({
|
|
149
|
+
"title": event.get("subject", "(No title)"),
|
|
150
|
+
"event_id": event.get("id"),
|
|
151
|
+
"start": start.get("dateTime", ""),
|
|
152
|
+
"end": end.get("dateTime", ""),
|
|
153
|
+
"all_day": event.get("isAllDay", False),
|
|
154
|
+
"description": description,
|
|
155
|
+
"location": event.get("location", {}).get("displayName", ""),
|
|
156
|
+
"status": event.get("showAs", ""),
|
|
157
|
+
"web_link": event.get("webLink", "")
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
return json.dumps({
|
|
161
|
+
"provider": "outlook",
|
|
162
|
+
"date": self.date,
|
|
163
|
+
"timezone": self.timezone,
|
|
164
|
+
"count": len(formatted_events),
|
|
165
|
+
"events": formatted_events
|
|
166
|
+
}, indent=2)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
import sys
|
|
171
|
+
import os
|
|
172
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../..")))
|
|
173
|
+
|
|
174
|
+
from datetime import date as dt_date
|
|
175
|
+
|
|
176
|
+
print("=" * 60)
|
|
177
|
+
print("CheckEventsForDate Test Suite")
|
|
178
|
+
print("=" * 60)
|
|
179
|
+
print()
|
|
180
|
+
|
|
181
|
+
today = dt_date.today().strftime("%Y-%m-%d")
|
|
182
|
+
|
|
183
|
+
# Test 1: Google Calendar for today
|
|
184
|
+
print(f"Test 1: Google Calendar - Today ({today})")
|
|
185
|
+
print("-" * 60)
|
|
186
|
+
tool = CheckEventsForDate(provider="google", date=today)
|
|
187
|
+
result = tool.run()
|
|
188
|
+
print(result)
|
|
189
|
+
print()
|
|
190
|
+
|
|
191
|
+
# Test 2: Google Calendar with custom timezone
|
|
192
|
+
print("Test 2: Google Calendar - Today with timezone")
|
|
193
|
+
print("-" * 60)
|
|
194
|
+
tool = CheckEventsForDate(provider="google", date=today, timezone="Asia/Dubai")
|
|
195
|
+
result = tool.run()
|
|
196
|
+
print(result)
|
|
197
|
+
print()
|
|
198
|
+
|
|
199
|
+
# Test 3: Outlook for today
|
|
200
|
+
print(f"Test 3: Outlook - Today ({today})")
|
|
201
|
+
print("-" * 60)
|
|
202
|
+
tool = CheckEventsForDate(provider="outlook", date=today)
|
|
203
|
+
result = tool.run()
|
|
204
|
+
print(result)
|
|
205
|
+
print()
|
|
206
|
+
|
|
207
|
+
# Test 4: Invalid date format
|
|
208
|
+
print("Test 4: Invalid date format")
|
|
209
|
+
print("-" * 60)
|
|
210
|
+
tool = CheckEventsForDate(provider="google", date="01-07-2026")
|
|
211
|
+
result = tool.run()
|
|
212
|
+
print(result)
|
|
213
|
+
print()
|
|
214
|
+
|
|
215
|
+
print("=" * 60)
|
|
216
|
+
print("All tests completed!")
|
|
217
|
+
print("=" * 60)
|
|
218
|
+
|