@_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,184 @@
|
|
|
1
|
+
import tempfile
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from bs4 import BeautifulSoup
|
|
6
|
+
from playwright.sync_api import sync_playwright
|
|
7
|
+
import subprocess
|
|
8
|
+
from .html_docx_page import _extract_page_geometry_pt
|
|
9
|
+
|
|
10
|
+
_PT_TO_PX = 96.0 / 72.0
|
|
11
|
+
|
|
12
|
+
# Elements that must never be split across a page boundary.
|
|
13
|
+
_UNSPLITTABLE_SELECTORS = "table, img, figure, blockquote, pre, svg"
|
|
14
|
+
|
|
15
|
+
# CSS applied to the inserted page-break div.
|
|
16
|
+
_PB_STYLE = "page-break-before:always;break-before:page;margin:0;padding:0;height:0;"
|
|
17
|
+
|
|
18
|
+
# Block-level tags whose children can directly receive a page-break sibling.
|
|
19
|
+
_BLOCK_PARENTS = frozenset(["BODY", "DIV", "TD", "TH", "SECTION", "ARTICLE", "MAIN"])
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def auto_page_breaks(html_content: str) -> str:
|
|
23
|
+
"""Insert page-break divs before unsplittable elements that cross a page boundary.
|
|
24
|
+
|
|
25
|
+
Renders the HTML in a single Playwright session at A4 width, identifies every
|
|
26
|
+
table / img / figure / blockquote / pre / svg whose bounding box crosses a page
|
|
27
|
+
boundary, and inserts a zero-height page-break-before div directly before it in
|
|
28
|
+
the live DOM. The modified HTML is returned via page.content().
|
|
29
|
+
|
|
30
|
+
No thresholds — if the element crosses any boundary, it moves to the next page.
|
|
31
|
+
"""
|
|
32
|
+
with tempfile.NamedTemporaryFile(
|
|
33
|
+
suffix=".html", delete=False, mode="w", encoding="utf-8"
|
|
34
|
+
) as fh:
|
|
35
|
+
fh.write(html_content)
|
|
36
|
+
tmp_path = Path(fh.name)
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
with sync_playwright() as playwright:
|
|
40
|
+
browser = _launch_chromium_with_install(playwright)
|
|
41
|
+
viewport_width_px, page_height_px = _extract_page_geometry_px(html_content)
|
|
42
|
+
page = browser.new_page(
|
|
43
|
+
viewport={"width": viewport_width_px, "height": page_height_px * 20}
|
|
44
|
+
)
|
|
45
|
+
page.emulate_media(media="print")
|
|
46
|
+
page.route(
|
|
47
|
+
"**/*",
|
|
48
|
+
lambda route, request: route.abort()
|
|
49
|
+
if request.resource_type in {"media", "font"}
|
|
50
|
+
else route.continue_(),
|
|
51
|
+
)
|
|
52
|
+
page.goto(tmp_path.as_uri(), wait_until="load")
|
|
53
|
+
|
|
54
|
+
block_parents_js = str(list(_BLOCK_PARENTS))
|
|
55
|
+
page.evaluate(
|
|
56
|
+
f"""([selectors, pageH, pbStyle]) => {{
|
|
57
|
+
const BLOCK_PARENTS = new Set({block_parents_js});
|
|
58
|
+
const processed = new WeakSet();
|
|
59
|
+
|
|
60
|
+
for (const el of document.querySelectorAll(selectors)) {{
|
|
61
|
+
const rect = el.getBoundingClientRect();
|
|
62
|
+
if (rect.height <= 0) continue;
|
|
63
|
+
|
|
64
|
+
// Mark tables that fit within one page — the DOCX converter will
|
|
65
|
+
// apply w:cantSplit to their rows so Word keeps them together.
|
|
66
|
+
if (el.tagName === 'TABLE' && rect.height < pageH) {{
|
|
67
|
+
el.setAttribute('data-docx-cant-split', '1');
|
|
68
|
+
}}
|
|
69
|
+
|
|
70
|
+
// Inject page-break before unsplittable elements that cross a boundary.
|
|
71
|
+
if (rect.height >= pageH) continue;
|
|
72
|
+
const topPage = Math.floor(rect.top / pageH);
|
|
73
|
+
const botPage = Math.floor((rect.bottom - 1) / pageH);
|
|
74
|
+
if (topPage === botPage) continue;
|
|
75
|
+
|
|
76
|
+
let node = el;
|
|
77
|
+
while (node.parentElement && !BLOCK_PARENTS.has(node.parentElement.tagName))
|
|
78
|
+
node = node.parentElement;
|
|
79
|
+
|
|
80
|
+
if (!node.parentElement) continue;
|
|
81
|
+
if (processed.has(node)) continue;
|
|
82
|
+
processed.add(node);
|
|
83
|
+
|
|
84
|
+
const pb = document.createElement('div');
|
|
85
|
+
pb.setAttribute('style', pbStyle);
|
|
86
|
+
node.parentElement.insertBefore(pb, node);
|
|
87
|
+
}}
|
|
88
|
+
}}""",
|
|
89
|
+
[_UNSPLITTABLE_SELECTORS, page_height_px, _PB_STYLE],
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
modified_html = page.content()
|
|
93
|
+
browser.close()
|
|
94
|
+
finally:
|
|
95
|
+
tmp_path.unlink(missing_ok=True)
|
|
96
|
+
|
|
97
|
+
return modified_html
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _extract_page_geometry_px(html_content: str) -> tuple[int, int]:
|
|
101
|
+
width_pt, height_pt, top_pt, _right_pt, bottom_pt, _left_pt = _extract_page_geometry_pt(
|
|
102
|
+
html_content
|
|
103
|
+
)
|
|
104
|
+
viewport_width_px = max(1, round(width_pt * _PT_TO_PX))
|
|
105
|
+
content_height_pt = max(1.0, height_pt - top_pt - bottom_pt)
|
|
106
|
+
page_height_px = max(1, round(content_height_pt * _PT_TO_PX))
|
|
107
|
+
return viewport_width_px, page_height_px
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _annotate_tables(soup: BeautifulSoup) -> str:
|
|
111
|
+
tables = soup.find_all("table")
|
|
112
|
+
for idx, table in enumerate(tables):
|
|
113
|
+
table["data-docx-table-idx"] = str(idx)
|
|
114
|
+
return str(soup)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _compute_table_auto_widths(html_content: str) -> dict[int, list[float]]:
|
|
118
|
+
widths_by_index: dict[int, list[float]] = {}
|
|
119
|
+
with sync_playwright() as playwright:
|
|
120
|
+
browser = _launch_chromium_with_install(playwright)
|
|
121
|
+
page = browser.new_page(viewport={"width": 1200, "height": 1600})
|
|
122
|
+
page.route(
|
|
123
|
+
"**/*",
|
|
124
|
+
lambda route, request: route.abort()
|
|
125
|
+
if request.resource_type in {"image", "media", "font"}
|
|
126
|
+
else route.continue_(),
|
|
127
|
+
)
|
|
128
|
+
page.set_content(html_content, wait_until="domcontentloaded")
|
|
129
|
+
tables = page.query_selector_all("table[data-docx-table-idx]")
|
|
130
|
+
for table in tables:
|
|
131
|
+
idx_value = table.get_attribute("data-docx-table-idx")
|
|
132
|
+
if idx_value is None:
|
|
133
|
+
continue
|
|
134
|
+
rows = table.query_selector_all("tr")
|
|
135
|
+
if not rows:
|
|
136
|
+
continue
|
|
137
|
+
row = rows[0]
|
|
138
|
+
cells = row.query_selector_all(":scope > td, :scope > th")
|
|
139
|
+
if not cells:
|
|
140
|
+
continue
|
|
141
|
+
widths_px = []
|
|
142
|
+
for cell in cells:
|
|
143
|
+
box = cell.bounding_box()
|
|
144
|
+
if box:
|
|
145
|
+
widths_px.append(box["width"])
|
|
146
|
+
if widths_px:
|
|
147
|
+
widths_by_index[int(idx_value)] = [width * 0.75 for width in widths_px]
|
|
148
|
+
browser.close()
|
|
149
|
+
return widths_by_index
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _extract_auto_widths(
|
|
153
|
+
table_node, table_auto_widths: dict[int, list[float]], column_count: int
|
|
154
|
+
) -> Optional[list[float]]:
|
|
155
|
+
idx_value = table_node.get("data-docx-table-idx")
|
|
156
|
+
if idx_value is None:
|
|
157
|
+
return None
|
|
158
|
+
try:
|
|
159
|
+
idx = int(idx_value)
|
|
160
|
+
except ValueError:
|
|
161
|
+
return None
|
|
162
|
+
widths = table_auto_widths.get(idx)
|
|
163
|
+
if not widths or len(widths) < column_count:
|
|
164
|
+
return None
|
|
165
|
+
return widths[:column_count]
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _launch_chromium_with_install(playwright_instance):
|
|
169
|
+
try:
|
|
170
|
+
return playwright_instance.chromium.launch()
|
|
171
|
+
except Exception as exc:
|
|
172
|
+
if _is_missing_playwright_browser_error(exc):
|
|
173
|
+
_install_playwright_chromium()
|
|
174
|
+
return playwright_instance.chromium.launch()
|
|
175
|
+
raise
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _is_missing_playwright_browser_error(exc: Exception) -> bool:
|
|
179
|
+
message = str(exc)
|
|
180
|
+
return "Executable doesn't exist" in message or "playwright install" in message
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _install_playwright_chromium() -> None:
|
|
184
|
+
subprocess.run(["playwright", "install", "chromium"], check=True)
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
from typing import Dict, List, Optional, Tuple
|
|
2
|
+
|
|
3
|
+
from bs4 import BeautifulSoup
|
|
4
|
+
from bs4.element import Tag
|
|
5
|
+
import tinycss2
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _parse_style(style: str) -> Dict[str, str]:
|
|
9
|
+
items = {}
|
|
10
|
+
for rule in style.split(";"):
|
|
11
|
+
if ":" not in rule:
|
|
12
|
+
continue
|
|
13
|
+
key, value = rule.split(":", 1)
|
|
14
|
+
key = key.strip().lower()
|
|
15
|
+
value = value.strip()
|
|
16
|
+
if key and value:
|
|
17
|
+
items[key] = value
|
|
18
|
+
return items
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _extract_css_rules(
|
|
22
|
+
soup: BeautifulSoup,
|
|
23
|
+
) -> List[Tuple[str, Dict[str, str], Tuple[int, int, int], int]]:
|
|
24
|
+
rules: List[Tuple[str, Dict[str, str], Tuple[int, int, int], int]] = []
|
|
25
|
+
order = 0
|
|
26
|
+
|
|
27
|
+
for style_tag in soup.find_all("style"):
|
|
28
|
+
css_text = style_tag.string or style_tag.get_text()
|
|
29
|
+
if not css_text:
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
stylesheet = tinycss2.parse_stylesheet(
|
|
33
|
+
css_text, skip_comments=True, skip_whitespace=True
|
|
34
|
+
)
|
|
35
|
+
for rule in stylesheet:
|
|
36
|
+
if rule.type != "qualified-rule":
|
|
37
|
+
continue
|
|
38
|
+
|
|
39
|
+
selectors_text = tinycss2.serialize(rule.prelude).strip()
|
|
40
|
+
if not selectors_text:
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
declarations = tinycss2.parse_declaration_list(
|
|
44
|
+
rule.content, skip_comments=True, skip_whitespace=True
|
|
45
|
+
)
|
|
46
|
+
style_map: Dict[str, str] = {}
|
|
47
|
+
for declaration in declarations:
|
|
48
|
+
if declaration.type != "declaration":
|
|
49
|
+
continue
|
|
50
|
+
name = declaration.name.lower().strip() if declaration.name else ""
|
|
51
|
+
value = tinycss2.serialize(declaration.value).strip()
|
|
52
|
+
if name and value:
|
|
53
|
+
style_map[name] = value
|
|
54
|
+
|
|
55
|
+
for selector in [s.strip() for s in selectors_text.split(",") if s.strip()]:
|
|
56
|
+
pseudo = None
|
|
57
|
+
if "::before" in selector:
|
|
58
|
+
pseudo = "before"
|
|
59
|
+
base_selector = selector.replace("::before", "").strip()
|
|
60
|
+
elif "::after" in selector:
|
|
61
|
+
pseudo = "after"
|
|
62
|
+
base_selector = selector.replace("::after", "").strip()
|
|
63
|
+
else:
|
|
64
|
+
base_selector = selector
|
|
65
|
+
|
|
66
|
+
if not _is_supported_selector(base_selector):
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
rule_styles = style_map
|
|
70
|
+
if pseudo:
|
|
71
|
+
rule_styles = {f"pseudo-{pseudo}-{k}": v for k, v in style_map.items()}
|
|
72
|
+
|
|
73
|
+
specificity = _selector_specificity(base_selector)
|
|
74
|
+
rules.append((base_selector, rule_styles, specificity, order))
|
|
75
|
+
order += 1
|
|
76
|
+
|
|
77
|
+
return rules
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _compute_style_map(
|
|
81
|
+
element, css_rules: List[Tuple[str, Dict[str, str], Tuple[int, int, int], int]]
|
|
82
|
+
) -> Dict[str, str]:
|
|
83
|
+
resolved: Dict[str, str] = {}
|
|
84
|
+
matches: List[Tuple[Tuple[int, int, int], int, Dict[str, str]]] = []
|
|
85
|
+
|
|
86
|
+
for selector, styles, specificity, order in css_rules:
|
|
87
|
+
if _matches_selector(element, selector):
|
|
88
|
+
matches.append((specificity, order, styles))
|
|
89
|
+
|
|
90
|
+
matches.sort(key=lambda item: (item[0], item[1]))
|
|
91
|
+
for _, __, styles in matches:
|
|
92
|
+
resolved.update(styles)
|
|
93
|
+
|
|
94
|
+
inline_styles = _parse_style(element.get("style", ""))
|
|
95
|
+
resolved.update(inline_styles)
|
|
96
|
+
|
|
97
|
+
return resolved
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _is_supported_selector(selector: str) -> bool:
|
|
101
|
+
selector = selector.strip()
|
|
102
|
+
if not selector:
|
|
103
|
+
return False
|
|
104
|
+
if any(token in selector for token in ["#", "[", "]", "*", "+", "~"]):
|
|
105
|
+
return False
|
|
106
|
+
return True
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _selector_specificity(selector: str) -> Tuple[int, int, int]:
|
|
110
|
+
selectors = _parse_selector_chain(selector)
|
|
111
|
+
class_count = sum(len(classes) for _, classes in selectors)
|
|
112
|
+
tag_count = sum(1 for tag, _ in selectors if tag)
|
|
113
|
+
return (0, class_count, tag_count)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _parse_selector(selector: str) -> Tuple[Optional[str], List[str]]:
|
|
117
|
+
selector = selector.strip()
|
|
118
|
+
if selector.startswith("."):
|
|
119
|
+
tag = None
|
|
120
|
+
classes = [cls for cls in selector[1:].split(".") if cls]
|
|
121
|
+
else:
|
|
122
|
+
parts = [part for part in selector.split(".") if part]
|
|
123
|
+
tag = parts[0] if parts else None
|
|
124
|
+
classes = parts[1:] if len(parts) > 1 else []
|
|
125
|
+
return tag, classes
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _matches_selector(element, selector: str) -> bool:
|
|
129
|
+
chain = _parse_selector_chain(selector)
|
|
130
|
+
if not chain:
|
|
131
|
+
return False
|
|
132
|
+
return _matches_selector_chain(element, chain)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _parse_selector_chain(selector: str) -> List[Tuple[Optional[str], List[str]]]:
|
|
136
|
+
tokens = selector.replace(">", " > ").split()
|
|
137
|
+
if not tokens:
|
|
138
|
+
return []
|
|
139
|
+
selectors: List[Tuple[Optional[str], List[str]]] = []
|
|
140
|
+
for token in tokens:
|
|
141
|
+
if token == ">":
|
|
142
|
+
selectors.append((">", []))
|
|
143
|
+
else:
|
|
144
|
+
selectors.append(_parse_selector(token))
|
|
145
|
+
return selectors
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _matches_selector_chain(element: Tag, chain: List[Tuple[Optional[str], List[str]]]) -> bool:
|
|
149
|
+
idx = len(chain) - 1
|
|
150
|
+
current = element
|
|
151
|
+
|
|
152
|
+
while idx >= 0:
|
|
153
|
+
token = chain[idx]
|
|
154
|
+
if token[0] == ">":
|
|
155
|
+
idx -= 1
|
|
156
|
+
if idx < 0:
|
|
157
|
+
return False
|
|
158
|
+
parent_selector = chain[idx]
|
|
159
|
+
current = current.parent if isinstance(current.parent, Tag) else None
|
|
160
|
+
if current is None or not _matches_simple_selector(current, parent_selector):
|
|
161
|
+
return False
|
|
162
|
+
idx -= 1
|
|
163
|
+
continue
|
|
164
|
+
|
|
165
|
+
if not _matches_simple_selector(current, token):
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
idx -= 1
|
|
169
|
+
if idx >= 0 and chain[idx][0] != ">":
|
|
170
|
+
ancestor_selector = chain[idx]
|
|
171
|
+
matched = False
|
|
172
|
+
ancestor = current.parent
|
|
173
|
+
while isinstance(ancestor, Tag):
|
|
174
|
+
if _matches_simple_selector(ancestor, ancestor_selector):
|
|
175
|
+
matched = True
|
|
176
|
+
current = ancestor
|
|
177
|
+
break
|
|
178
|
+
ancestor = ancestor.parent
|
|
179
|
+
if not matched:
|
|
180
|
+
return False
|
|
181
|
+
idx -= 1
|
|
182
|
+
|
|
183
|
+
return True
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _matches_simple_selector(
|
|
187
|
+
element: Tag, selector: Tuple[Optional[str], List[str]]
|
|
188
|
+
) -> bool:
|
|
189
|
+
tag, classes = selector
|
|
190
|
+
if tag and element.name != tag:
|
|
191
|
+
return False
|
|
192
|
+
if classes:
|
|
193
|
+
element_classes = set(element.get("class", []))
|
|
194
|
+
if not all(cls in element_classes for cls in classes):
|
|
195
|
+
return False
|
|
196
|
+
return True
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
def _remove_trailing_empty_paragraph(container) -> None:
|
|
2
|
+
if not hasattr(container, "paragraphs"):
|
|
3
|
+
return
|
|
4
|
+
if not container.paragraphs:
|
|
5
|
+
return
|
|
6
|
+
last = container.paragraphs[-1]
|
|
7
|
+
if last.text.strip():
|
|
8
|
+
return
|
|
9
|
+
# Preserve empty paragraphs that carry a visual border (used as divider lines).
|
|
10
|
+
if "<w:pBdr>" in last._p.xml:
|
|
11
|
+
return
|
|
12
|
+
last._element.getparent().remove(last._element)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _remove_leading_empty_paragraph(container) -> None:
|
|
16
|
+
if not hasattr(container, "paragraphs"):
|
|
17
|
+
return
|
|
18
|
+
if not container.paragraphs:
|
|
19
|
+
return
|
|
20
|
+
first = container.paragraphs[0]
|
|
21
|
+
if first.text.strip():
|
|
22
|
+
return
|
|
23
|
+
first._element.getparent().remove(first._element)
|