@_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.
Files changed (316) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +152 -0
  3. package/bin/openswarm.js +38 -0
  4. package/config.py +34 -0
  5. package/data_analyst_agent/.cursor/rules/data_analyst.mdc +43 -0
  6. package/data_analyst_agent/__init__.py +3 -0
  7. package/data_analyst_agent/__pycache__/__init__.cpython-312.pyc +0 -0
  8. package/data_analyst_agent/__pycache__/data_analyst_agent.cpython-312.pyc +0 -0
  9. package/data_analyst_agent/data_analyst_agent.py +45 -0
  10. package/data_analyst_agent/instructions.md +173 -0
  11. package/data_analyst_agent/test_files/test_file.csv +21 -0
  12. package/data_analyst_agent/tools/__init__.py +6 -0
  13. package/deep_research/__init__.py +1 -0
  14. package/deep_research/__pycache__/__init__.cpython-312.pyc +0 -0
  15. package/deep_research/__pycache__/deep_research.cpython-312.pyc +0 -0
  16. package/deep_research/deep_research.py +27 -0
  17. package/deep_research/instructions.md +104 -0
  18. package/deep_research/tools/__init__.py +1 -0
  19. package/docs_agent/__init__.py +3 -0
  20. package/docs_agent/__pycache__/__init__.cpython-312.pyc +0 -0
  21. package/docs_agent/__pycache__/docs_agent.cpython-312.pyc +0 -0
  22. package/docs_agent/docs_agent.py +61 -0
  23. package/docs_agent/instructions.md +418 -0
  24. package/docs_agent/tools/ConvertDocument.py +323 -0
  25. package/docs_agent/tools/CreateDocument.py +287 -0
  26. package/docs_agent/tools/ListDocuments.py +134 -0
  27. package/docs_agent/tools/ModifyDocument.py +247 -0
  28. package/docs_agent/tools/RestoreDocument.py +79 -0
  29. package/docs_agent/tools/ViewDocument.py +153 -0
  30. package/docs_agent/tools/__init__.py +1 -0
  31. package/docs_agent/tools/__pycache__/ConvertDocument.cpython-312.pyc +0 -0
  32. package/docs_agent/tools/__pycache__/CreateDocument.cpython-312.pyc +0 -0
  33. package/docs_agent/tools/__pycache__/ListDocuments.cpython-312.pyc +0 -0
  34. package/docs_agent/tools/__pycache__/ModifyDocument.cpython-312.pyc +0 -0
  35. package/docs_agent/tools/__pycache__/RestoreDocument.cpython-312.pyc +0 -0
  36. package/docs_agent/tools/__pycache__/ViewDocument.cpython-312.pyc +0 -0
  37. package/docs_agent/tools/__pycache__/__init__.cpython-312.pyc +0 -0
  38. package/docs_agent/tools/utils/__init__.py +1 -0
  39. package/docs_agent/tools/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  40. package/docs_agent/tools/utils/__pycache__/doc_file_utils.cpython-312.pyc +0 -0
  41. package/docs_agent/tools/utils/__pycache__/html_docx_blocks.cpython-312.pyc +0 -0
  42. package/docs_agent/tools/utils/__pycache__/html_docx_constants.cpython-312.pyc +0 -0
  43. package/docs_agent/tools/utils/__pycache__/html_docx_core.cpython-312.pyc +0 -0
  44. package/docs_agent/tools/utils/__pycache__/html_docx_css.cpython-312.pyc +0 -0
  45. package/docs_agent/tools/utils/__pycache__/html_docx_images.cpython-312.pyc +0 -0
  46. package/docs_agent/tools/utils/__pycache__/html_docx_page.cpython-312.pyc +0 -0
  47. package/docs_agent/tools/utils/__pycache__/html_docx_paragraphs.cpython-312.pyc +0 -0
  48. package/docs_agent/tools/utils/__pycache__/html_docx_playwright.cpython-312.pyc +0 -0
  49. package/docs_agent/tools/utils/__pycache__/html_docx_selectors.cpython-312.pyc +0 -0
  50. package/docs_agent/tools/utils/__pycache__/html_docx_shared.cpython-312.pyc +0 -0
  51. package/docs_agent/tools/utils/__pycache__/html_validation.cpython-312.pyc +0 -0
  52. package/docs_agent/tools/utils/doc_file_utils.py +29 -0
  53. package/docs_agent/tools/utils/html_docx_blocks.py +262 -0
  54. package/docs_agent/tools/utils/html_docx_constants.py +78 -0
  55. package/docs_agent/tools/utils/html_docx_core.py +138 -0
  56. package/docs_agent/tools/utils/html_docx_css.py +262 -0
  57. package/docs_agent/tools/utils/html_docx_images.py +293 -0
  58. package/docs_agent/tools/utils/html_docx_page.py +185 -0
  59. package/docs_agent/tools/utils/html_docx_paragraphs.py +342 -0
  60. package/docs_agent/tools/utils/html_docx_playwright.py +184 -0
  61. package/docs_agent/tools/utils/html_docx_selectors.py +196 -0
  62. package/docs_agent/tools/utils/html_docx_shared.py +23 -0
  63. package/docs_agent/tools/utils/html_docx_tables.py +942 -0
  64. package/docs_agent/tools/utils/html_validation.py +102 -0
  65. package/helpers.py +59 -0
  66. package/image_generation_agent/__init__.py +1 -0
  67. package/image_generation_agent/__pycache__/__init__.cpython-312.pyc +0 -0
  68. package/image_generation_agent/__pycache__/image_generation_agent.cpython-312.pyc +0 -0
  69. package/image_generation_agent/image_generation_agent.py +31 -0
  70. package/image_generation_agent/instructions.md +80 -0
  71. package/image_generation_agent/tools/CombineImages.py +211 -0
  72. package/image_generation_agent/tools/EditImages.py +200 -0
  73. package/image_generation_agent/tools/GenerateImages.py +184 -0
  74. package/image_generation_agent/tools/RemoveBackground.py +108 -0
  75. package/image_generation_agent/tools/__init__.py +2 -0
  76. package/image_generation_agent/tools/__pycache__/CombineImages.cpython-312.pyc +0 -0
  77. package/image_generation_agent/tools/__pycache__/EditImages.cpython-312.pyc +0 -0
  78. package/image_generation_agent/tools/__pycache__/GenerateImages.cpython-312.pyc +0 -0
  79. package/image_generation_agent/tools/__pycache__/RemoveBackground.cpython-312.pyc +0 -0
  80. package/image_generation_agent/tools/utils/__init__.py +2 -0
  81. package/image_generation_agent/tools/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  82. package/image_generation_agent/tools/utils/__pycache__/image_io.cpython-312.pyc +0 -0
  83. package/image_generation_agent/tools/utils/image_io.py +308 -0
  84. package/onboard.py +325 -0
  85. package/orchestrator/__init__.py +3 -0
  86. package/orchestrator/__pycache__/__init__.cpython-312.pyc +0 -0
  87. package/orchestrator/__pycache__/orchestrator.cpython-312.pyc +0 -0
  88. package/orchestrator/instructions.md +90 -0
  89. package/orchestrator/orchestrator.py +33 -0
  90. package/package.json +49 -0
  91. package/patches/__init__.py +1 -0
  92. package/patches/__pycache__/__init__.cpython-312.pyc +0 -0
  93. package/patches/__pycache__/patch_agency_swarm_dual_comms.cpython-312.pyc +0 -0
  94. package/patches/__pycache__/patch_file_attachment_refs.cpython-312.pyc +0 -0
  95. package/patches/__pycache__/patch_ipython_interpreter_composio.cpython-312.pyc +0 -0
  96. package/patches/dom-to-pptx+1.1.5.patch +133440 -0
  97. package/patches/patch_agency_swarm_dual_comms.py +199 -0
  98. package/patches/patch_file_attachment_refs.py +74 -0
  99. package/patches/patch_ipython_interpreter_composio.py +54 -0
  100. package/pyproject.toml +67 -0
  101. package/run.py +343 -0
  102. package/server.py +26 -0
  103. package/shared_instructions.md +119 -0
  104. package/shared_tools/CopyFile.py +68 -0
  105. package/shared_tools/ExecuteTool.py +184 -0
  106. package/shared_tools/FindTools.py +101 -0
  107. package/shared_tools/ManageConnections.py +43 -0
  108. package/shared_tools/SearchTools.py +44 -0
  109. package/shared_tools/__init__.py +7 -0
  110. package/shared_tools/__pycache__/CopyFile.cpython-312.pyc +0 -0
  111. package/shared_tools/__pycache__/ExecuteTool.cpython-312.pyc +0 -0
  112. package/shared_tools/__pycache__/FindTools.cpython-312.pyc +0 -0
  113. package/shared_tools/__pycache__/ManageConnections.cpython-312.pyc +0 -0
  114. package/shared_tools/__pycache__/SearchTools.cpython-312.pyc +0 -0
  115. package/shared_tools/__pycache__/__init__.cpython-312.pyc +0 -0
  116. package/slides_agent/.cursor/rules/slides-agent-workflow.mdc +9 -0
  117. package/slides_agent/__init__.py +1 -0
  118. package/slides_agent/__pycache__/__init__.cpython-312.pyc +0 -0
  119. package/slides_agent/__pycache__/slides_agent.cpython-312.pyc +0 -0
  120. package/slides_agent/instructions.md +298 -0
  121. package/slides_agent/pptx/SKILL.md +528 -0
  122. package/slides_agent/pptx/html2pptx.md +625 -0
  123. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  124. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  125. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  126. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  127. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  128. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  129. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  130. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  131. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  132. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  133. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  134. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  135. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  136. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  137. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  138. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  139. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  140. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  141. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  142. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  143. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  144. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  145. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  146. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  147. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  148. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  149. package/slides_agent/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  150. package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  151. package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  152. package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  153. package/slides_agent/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  154. package/slides_agent/pptx/ooxml/schemas/mce/mc.xsd +75 -0
  155. package/slides_agent/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
  156. package/slides_agent/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
  157. package/slides_agent/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
  158. package/slides_agent/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
  159. package/slides_agent/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
  160. package/slides_agent/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  161. package/slides_agent/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
  162. package/slides_agent/pptx/ooxml/scripts/pack.py +169 -0
  163. package/slides_agent/pptx/ooxml/scripts/unpack.py +29 -0
  164. package/slides_agent/pptx/ooxml/scripts/validate.py +69 -0
  165. package/slides_agent/pptx/ooxml/scripts/validation/__init__.py +15 -0
  166. package/slides_agent/pptx/ooxml/scripts/validation/base.py +951 -0
  167. package/slides_agent/pptx/ooxml/scripts/validation/docx.py +274 -0
  168. package/slides_agent/pptx/ooxml/scripts/validation/pptx.py +315 -0
  169. package/slides_agent/pptx/ooxml/scripts/validation/redlining.py +279 -0
  170. package/slides_agent/pptx/ooxml.md +427 -0
  171. package/slides_agent/pptx/scripts/html2pptx.js +1092 -0
  172. package/slides_agent/pptx/scripts/inventory.py +1020 -0
  173. package/slides_agent/pptx/scripts/rearrange.py +231 -0
  174. package/slides_agent/pptx/scripts/replace.py +385 -0
  175. package/slides_agent/pptx/scripts/thumbnail.py +451 -0
  176. package/slides_agent/slides_agent.py +109 -0
  177. package/slides_agent/test_deck/_theme.css +92 -0
  178. package/slides_agent/test_deck/assets/placeholder.svg +11 -0
  179. package/slides_agent/test_deck/slide_01_title.html +10 -0
  180. package/slides_agent/test_deck/slide_02_image_split.html +23 -0
  181. package/slides_agent/test_deck/slide_03_kpi.html +21 -0
  182. package/slides_agent/tools/ApplyPptxTextReplacements.py +91 -0
  183. package/slides_agent/tools/BuildPptxFromHtmlSlides.py +221 -0
  184. package/slides_agent/tools/CheckSlide.py +218 -0
  185. package/slides_agent/tools/CheckSlideCanvasOverflow.py +221 -0
  186. package/slides_agent/tools/CreateImageMontage.py +261 -0
  187. package/slides_agent/tools/CreatePptxThumbnailGrid.py +168 -0
  188. package/slides_agent/tools/DeleteSlide.py +78 -0
  189. package/slides_agent/tools/DownloadImage.py +79 -0
  190. package/slides_agent/tools/EnsureRasterImage.py +157 -0
  191. package/slides_agent/tools/ExtractPptxTextInventory.py +104 -0
  192. package/slides_agent/tools/GenerateImage.py +189 -0
  193. package/slides_agent/tools/ImageSearch.py +127 -0
  194. package/slides_agent/tools/InsertNewSlides.py +393 -0
  195. package/slides_agent/tools/ManageTheme.py +112 -0
  196. package/slides_agent/tools/ModifySlide.py +563 -0
  197. package/slides_agent/tools/ReadSlide.py +26 -0
  198. package/slides_agent/tools/RearrangePptxSlidesFromTemplate.py +114 -0
  199. package/slides_agent/tools/RestoreSnapshot.py +89 -0
  200. package/slides_agent/tools/SlideScreenshot.py +66 -0
  201. package/slides_agent/tools/__init__.py +54 -0
  202. package/slides_agent/tools/__pycache__/ApplyPptxTextReplacements.cpython-312.pyc +0 -0
  203. package/slides_agent/tools/__pycache__/BuildPptxFromHtmlSlides.cpython-312.pyc +0 -0
  204. package/slides_agent/tools/__pycache__/CheckSlide.cpython-312.pyc +0 -0
  205. package/slides_agent/tools/__pycache__/CheckSlideCanvasOverflow.cpython-312.pyc +0 -0
  206. package/slides_agent/tools/__pycache__/CreateImageMontage.cpython-312.pyc +0 -0
  207. package/slides_agent/tools/__pycache__/CreatePptxThumbnailGrid.cpython-312.pyc +0 -0
  208. package/slides_agent/tools/__pycache__/DeleteSlide.cpython-312.pyc +0 -0
  209. package/slides_agent/tools/__pycache__/DownloadImage.cpython-312.pyc +0 -0
  210. package/slides_agent/tools/__pycache__/EnsureRasterImage.cpython-312.pyc +0 -0
  211. package/slides_agent/tools/__pycache__/ExtractPptxTextInventory.cpython-312.pyc +0 -0
  212. package/slides_agent/tools/__pycache__/GenerateImage.cpython-312.pyc +0 -0
  213. package/slides_agent/tools/__pycache__/ImageSearch.cpython-312.pyc +0 -0
  214. package/slides_agent/tools/__pycache__/InsertNewSlides.cpython-312.pyc +0 -0
  215. package/slides_agent/tools/__pycache__/ManageTheme.cpython-312.pyc +0 -0
  216. package/slides_agent/tools/__pycache__/ModifySlide.cpython-312.pyc +0 -0
  217. package/slides_agent/tools/__pycache__/ReadSlide.cpython-312.pyc +0 -0
  218. package/slides_agent/tools/__pycache__/RearrangePptxSlidesFromTemplate.cpython-312.pyc +0 -0
  219. package/slides_agent/tools/__pycache__/RestoreSnapshot.cpython-312.pyc +0 -0
  220. package/slides_agent/tools/__pycache__/SlideScreenshot.cpython-312.pyc +0 -0
  221. package/slides_agent/tools/__pycache__/__init__.cpython-312.pyc +0 -0
  222. package/slides_agent/tools/__pycache__/slide_file_utils.cpython-312.pyc +0 -0
  223. package/slides_agent/tools/__pycache__/slide_html_utils.cpython-312.pyc +0 -0
  224. package/slides_agent/tools/__pycache__/template_registry.cpython-312.pyc +0 -0
  225. package/slides_agent/tools/deck_utils.py +31 -0
  226. package/slides_agent/tools/html2pptx_runner.js +1183 -0
  227. package/slides_agent/tools/html_writer_instructions.md +149 -0
  228. package/slides_agent/tools/slide_file_utils.py +108 -0
  229. package/slides_agent/tools/slide_html_utils.py +354 -0
  230. package/slides_agent/tools/template_registry.py +55 -0
  231. package/swarm.py +82 -0
  232. package/video_generation_agent/__init__.py +1 -0
  233. package/video_generation_agent/__pycache__/__init__.cpython-312.pyc +0 -0
  234. package/video_generation_agent/__pycache__/video_generation_agent.cpython-312.pyc +0 -0
  235. package/video_generation_agent/instructions.md +178 -0
  236. package/video_generation_agent/tools/AddSubtitles.py +425 -0
  237. package/video_generation_agent/tools/CombineImages.py +166 -0
  238. package/video_generation_agent/tools/CombineVideos.py +113 -0
  239. package/video_generation_agent/tools/EditAudio.py +297 -0
  240. package/video_generation_agent/tools/EditImage.py +144 -0
  241. package/video_generation_agent/tools/EditVideoContent.py +369 -0
  242. package/video_generation_agent/tools/GenerateImage.py +133 -0
  243. package/video_generation_agent/tools/GenerateVideo.py +556 -0
  244. package/video_generation_agent/tools/TrimVideo.py +233 -0
  245. package/video_generation_agent/tools/__init__.py +1 -0
  246. package/video_generation_agent/tools/__pycache__/AddSubtitles.cpython-312.pyc +0 -0
  247. package/video_generation_agent/tools/__pycache__/CombineImages.cpython-312.pyc +0 -0
  248. package/video_generation_agent/tools/__pycache__/CombineVideos.cpython-312.pyc +0 -0
  249. package/video_generation_agent/tools/__pycache__/EditAudio.cpython-312.pyc +0 -0
  250. package/video_generation_agent/tools/__pycache__/EditImage.cpython-312.pyc +0 -0
  251. package/video_generation_agent/tools/__pycache__/EditVideoContent.cpython-312.pyc +0 -0
  252. package/video_generation_agent/tools/__pycache__/GenerateImage.cpython-312.pyc +0 -0
  253. package/video_generation_agent/tools/__pycache__/GenerateVideo.cpython-312.pyc +0 -0
  254. package/video_generation_agent/tools/__pycache__/TrimVideo.cpython-312.pyc +0 -0
  255. package/video_generation_agent/tools/utils/__init__.py +1 -0
  256. package/video_generation_agent/tools/utils/__pycache__/__init__.cpython-312.pyc +0 -0
  257. package/video_generation_agent/tools/utils/__pycache__/image_utils.cpython-312.pyc +0 -0
  258. package/video_generation_agent/tools/utils/__pycache__/video_utils.cpython-312.pyc +0 -0
  259. package/video_generation_agent/tools/utils/image_utils.py +174 -0
  260. package/video_generation_agent/tools/utils/video_utils.py +522 -0
  261. package/video_generation_agent/video_generation_agent.py +26 -0
  262. package/virtual_assistant/__init__.py +1 -0
  263. package/virtual_assistant/__pycache__/__init__.cpython-312.pyc +0 -0
  264. package/virtual_assistant/__pycache__/virtual_assistant.cpython-312.pyc +0 -0
  265. package/virtual_assistant/instructions.md +206 -0
  266. package/virtual_assistant/tools/AddLabelToEmail.py +154 -0
  267. package/virtual_assistant/tools/CheckEventsForDate.py +218 -0
  268. package/virtual_assistant/tools/CheckUnreadSlackMessages.py +216 -0
  269. package/virtual_assistant/tools/CreateCalendarEvent.py +261 -0
  270. package/virtual_assistant/tools/DeleteCalendarEvent.py +137 -0
  271. package/virtual_assistant/tools/DeleteDraft.py +95 -0
  272. package/virtual_assistant/tools/DraftEmail.py +239 -0
  273. package/virtual_assistant/tools/EditFile.py +113 -0
  274. package/virtual_assistant/tools/FindEmails.py +330 -0
  275. package/virtual_assistant/tools/GetCurrentTime.py +69 -0
  276. package/virtual_assistant/tools/GetSlackUserInfo.py +117 -0
  277. package/virtual_assistant/tools/ListDirectory.py +113 -0
  278. package/virtual_assistant/tools/ListSkills.py +94 -0
  279. package/virtual_assistant/tools/ManageLabels.py +295 -0
  280. package/virtual_assistant/tools/ProductSearch.py +254 -0
  281. package/virtual_assistant/tools/ReadEmail.py +251 -0
  282. package/virtual_assistant/tools/ReadFile.py +108 -0
  283. package/virtual_assistant/tools/ReadSlackMessages.py +191 -0
  284. package/virtual_assistant/tools/RemoveLabelFromEmail.py +137 -0
  285. package/virtual_assistant/tools/RescheduleCalendarEvent.py +227 -0
  286. package/virtual_assistant/tools/ScholarSearch.py +216 -0
  287. package/virtual_assistant/tools/SendDraft.py +101 -0
  288. package/virtual_assistant/tools/SendSlackMessage.py +148 -0
  289. package/virtual_assistant/tools/WriteFile.py +95 -0
  290. package/virtual_assistant/tools/__init__.py +1 -0
  291. package/virtual_assistant/tools/__pycache__/AddLabelToEmail.cpython-312.pyc +0 -0
  292. package/virtual_assistant/tools/__pycache__/CheckEventsForDate.cpython-312.pyc +0 -0
  293. package/virtual_assistant/tools/__pycache__/CheckUnreadSlackMessages.cpython-312.pyc +0 -0
  294. package/virtual_assistant/tools/__pycache__/CreateCalendarEvent.cpython-312.pyc +0 -0
  295. package/virtual_assistant/tools/__pycache__/DeleteCalendarEvent.cpython-312.pyc +0 -0
  296. package/virtual_assistant/tools/__pycache__/DeleteDraft.cpython-312.pyc +0 -0
  297. package/virtual_assistant/tools/__pycache__/DraftEmail.cpython-312.pyc +0 -0
  298. package/virtual_assistant/tools/__pycache__/EditFile.cpython-312.pyc +0 -0
  299. package/virtual_assistant/tools/__pycache__/FindEmails.cpython-312.pyc +0 -0
  300. package/virtual_assistant/tools/__pycache__/GetCurrentTime.cpython-312.pyc +0 -0
  301. package/virtual_assistant/tools/__pycache__/GetSlackUserInfo.cpython-312.pyc +0 -0
  302. package/virtual_assistant/tools/__pycache__/ListDirectory.cpython-312.pyc +0 -0
  303. package/virtual_assistant/tools/__pycache__/ListSkills.cpython-312.pyc +0 -0
  304. package/virtual_assistant/tools/__pycache__/ManageLabels.cpython-312.pyc +0 -0
  305. package/virtual_assistant/tools/__pycache__/ProductSearch.cpython-312.pyc +0 -0
  306. package/virtual_assistant/tools/__pycache__/ReadEmail.cpython-312.pyc +0 -0
  307. package/virtual_assistant/tools/__pycache__/ReadFile.cpython-312.pyc +0 -0
  308. package/virtual_assistant/tools/__pycache__/ReadSlackMessages.cpython-312.pyc +0 -0
  309. package/virtual_assistant/tools/__pycache__/RemoveLabelFromEmail.cpython-312.pyc +0 -0
  310. package/virtual_assistant/tools/__pycache__/RescheduleCalendarEvent.cpython-312.pyc +0 -0
  311. package/virtual_assistant/tools/__pycache__/ScholarSearch.cpython-312.pyc +0 -0
  312. package/virtual_assistant/tools/__pycache__/SendDraft.cpython-312.pyc +0 -0
  313. package/virtual_assistant/tools/__pycache__/SendSlackMessage.cpython-312.pyc +0 -0
  314. package/virtual_assistant/tools/__pycache__/WriteFile.cpython-312.pyc +0 -0
  315. package/virtual_assistant/tools/__pycache__/__init__.cpython-312.pyc +0 -0
  316. package/virtual_assistant/virtual_assistant.py +52 -0
@@ -0,0 +1,369 @@
1
+ """Tool for editing video content via fal.ai models."""
2
+
3
+ import asyncio
4
+ import logging
5
+ import os
6
+ import re
7
+ import cv2
8
+ import httpx
9
+ from typing import Annotated, Literal, Optional, Union
10
+
11
+ import fal_client
12
+ from pydantic import BaseModel, Field, field_validator
13
+ from google.genai import types
14
+ from PIL import Image
15
+
16
+ from agency_swarm import BaseTool, ToolOutputText
17
+
18
+ from .utils.video_utils import (
19
+ create_image_output,
20
+ extract_last_frame,
21
+ generate_spritesheet,
22
+ get_gemini_client,
23
+ get_openai_client,
24
+ save_video_with_metadata,
25
+ save_veo_video_with_metadata,
26
+ get_videos_dir,
27
+ )
28
+
29
+ _VEO_MODEL = "veo-3.1-generate-preview"
30
+
31
+ logger = logging.getLogger(__name__)
32
+
33
+
34
+ def _ensure_not_blank(value: str, field_name: str) -> str:
35
+ if not value.strip():
36
+ raise ValueError(f"{field_name} must not be empty")
37
+ return value
38
+
39
+
40
+ class EditMode(BaseModel):
41
+ action: Literal["edit"]
42
+ video_source: str = Field(
43
+ ...,
44
+ description="Source video path or HTTP/HTTPS URL.",
45
+ )
46
+ prompt: str = Field(
47
+ ...,
48
+ description="Editing prompt.",
49
+ )
50
+ reference_images: Optional[list[str]] = Field(
51
+ default=None,
52
+ description="Optional reference image paths or URLs.",
53
+ )
54
+
55
+ @field_validator("video_source")
56
+ @classmethod
57
+ def _video_source_not_blank(cls, value: str) -> str:
58
+ return _ensure_not_blank(value, "video_source")
59
+
60
+ @field_validator("prompt")
61
+ @classmethod
62
+ def _prompt_not_blank(cls, value: str) -> str:
63
+ if re.match(r"^\[.*\]", value) or re.match(r"^\[.*?\]\s+.+", value):
64
+ raise ValueError(
65
+ "PROMPT CANNOT CONTAIN VARIABLES. Rewrite the full prompt from scratch — "
66
+ "this tool is stateless and does not retain prior context."
67
+ )
68
+ return _ensure_not_blank(value, "prompt")
69
+
70
+
71
+ class RemixMode(BaseModel):
72
+ action: Literal["remix"]
73
+ video_id: str = Field(
74
+ ...,
75
+ description="Sora video ID to remix.",
76
+ )
77
+ prompt: str = Field(
78
+ ...,
79
+ description="Remix prompt.",
80
+ )
81
+
82
+ @field_validator("video_id")
83
+ @classmethod
84
+ def _video_id_not_blank(cls, value: str) -> str:
85
+ return _ensure_not_blank(value, "video_id")
86
+
87
+ @field_validator("prompt")
88
+ @classmethod
89
+ def _prompt_not_blank(cls, value: str) -> str:
90
+ if re.match(r"^\[.*\]", value) or re.match(r"^\[.*?\]\s+.+", value):
91
+ raise ValueError(
92
+ "PROMPT CANNOT CONTAIN VARIABLES. Rewrite the full prompt from scratch — "
93
+ "this tool is stateless and does not retain prior context."
94
+ )
95
+ return _ensure_not_blank(value, "prompt")
96
+
97
+
98
+ class ExtendMode(BaseModel):
99
+ action: Literal["extend"]
100
+ veo_video_ref: str = Field(
101
+ ...,
102
+ description=(
103
+ "Veo video reference from a previous Veo generation "
104
+ "(e.g., 'files/abc123' or a Veo download URL)."
105
+ ),
106
+ )
107
+ prompt: Optional[str] = Field(
108
+ default=None,
109
+ description="Optional extension prompt.",
110
+ )
111
+
112
+ @field_validator("veo_video_ref")
113
+ @classmethod
114
+ def _veo_video_ref_not_blank(cls, value: str) -> str:
115
+ return _ensure_not_blank(value, "veo_video_ref")
116
+
117
+ @field_validator("prompt")
118
+ @classmethod
119
+ def _prompt_not_blank(cls, value: Optional[str]) -> Optional[str]:
120
+ if value is None:
121
+ return value
122
+ if re.match(r"^\[.*\]", value) or re.match(r"^\[.*?\]\s+.+", value):
123
+ raise ValueError(
124
+ "PROMPT CANNOT CONTAIN VARIABLES. Rewrite the full prompt from scratch — "
125
+ "this tool is stateless and does not retain prior context."
126
+ )
127
+ return _ensure_not_blank(value, "prompt")
128
+
129
+
130
+ EditModeUnion = Annotated[
131
+ Union[EditMode, RemixMode, ExtendMode],
132
+ Field(discriminator="action"),
133
+ ]
134
+
135
+
136
+ class EditVideoContent(BaseTool):
137
+ """
138
+ Edit video content via fal.ai video-to-video models.
139
+
140
+ Videos are saved to: mnt/{product_name}/generated_videos/
141
+ """
142
+
143
+ product_name: str = Field(
144
+ ...,
145
+ description="Name of the product this video is for. Used to organize files into product-specific folders.",
146
+ )
147
+ name: str = Field(
148
+ ...,
149
+ description="The name for the edited video file (without extension)",
150
+ )
151
+ mode: Union[EditMode, RemixMode, ExtendMode] = Field(
152
+ ...,
153
+ description=(
154
+ "Action-specific inputs. Use the 'action' field to select which "
155
+ "mode shape is required."
156
+ ),
157
+ )
158
+
159
+ @field_validator("name")
160
+ @classmethod
161
+ def _name_not_blank(cls, value: str) -> str:
162
+ return _ensure_not_blank(value, "name")
163
+
164
+ async def run(self) -> list:
165
+ if self.mode.action == "remix":
166
+ return await self._run_remix(self.mode)
167
+ if self.mode.action == "extend":
168
+ return await self._run_extend(self.mode)
169
+
170
+ api_key = os.getenv("FAL_KEY")
171
+ if not api_key:
172
+ raise ValueError("FAL_KEY is not set. Add it to your .env to use video editing.")
173
+ fal = fal_client.SyncClient(key=api_key)
174
+
175
+ endpoint = self._resolve_endpoint(self.mode.action)
176
+ video_url = self._resolve_media_url(self.mode.video_source, fal)
177
+ arguments = {"video_url": video_url}
178
+
179
+ arguments["prompt"] = self.mode.prompt
180
+ if self.mode.reference_images:
181
+ arguments["image_urls"] = [
182
+ self._resolve_media_url(ref, fal) for ref in self.mode.reference_images
183
+ ]
184
+
185
+ result = fal.subscribe(endpoint, arguments=arguments, with_logs=True)
186
+ output_url = self._extract_video_url(result)
187
+
188
+ if not output_url:
189
+ raise RuntimeError("fal.ai response did not include a video URL")
190
+
191
+ videos_dir = get_videos_dir(self.product_name)
192
+ output_path = os.path.join(videos_dir, f"{self.name}.mp4")
193
+ self._download_file(output_url, output_path)
194
+
195
+ output = []
196
+
197
+ spritesheet_path = os.path.join(videos_dir, f"{self.name}_spritesheet.jpg")
198
+ spritesheet = generate_spritesheet(output_path, spritesheet_path)
199
+ if spritesheet:
200
+ output.extend(create_image_output(spritesheet_path, f"{self.name}_spritesheet.jpg"))
201
+
202
+ thumbnail_path = os.path.join(videos_dir, f"{self.name}_thumbnail.jpg")
203
+ thumbnail = self._extract_first_frame(output_path, thumbnail_path)
204
+ if thumbnail:
205
+ output.extend(create_image_output(thumbnail_path, f"{self.name}_thumbnail.jpg"))
206
+
207
+ last_frame_path = os.path.join(videos_dir, f"{self.name}_last_frame.jpg")
208
+ last_frame = extract_last_frame(output_path, last_frame_path)
209
+ if last_frame:
210
+ output.extend(create_image_output(last_frame_path, f"{self.name}_last_frame.jpg"))
211
+
212
+ output.append(
213
+ ToolOutputText(
214
+ type="text",
215
+ text=f"Video edit complete!\nSaved to: `{self.name}.mp4`\nPath: {output_path}",
216
+ )
217
+ )
218
+
219
+ return output
220
+
221
+ async def _run_remix(self, payload: RemixMode) -> list:
222
+ client = get_openai_client()
223
+ loop = asyncio.get_event_loop()
224
+
225
+ video = await loop.run_in_executor(
226
+ None,
227
+ lambda: client.videos.remix(video_id=payload.video_id, prompt=payload.prompt),
228
+ )
229
+ video = await loop.run_in_executor(None, lambda: client.videos.poll(video.id))
230
+ return save_video_with_metadata(client, video.id, self.name, self.product_name)
231
+
232
+ async def _run_extend(self, payload: ExtendMode) -> list:
233
+ client = get_gemini_client()
234
+ loop = asyncio.get_event_loop()
235
+
236
+ if payload.veo_video_ref.startswith("http://") or payload.veo_video_ref.startswith(
237
+ "https://"
238
+ ):
239
+ video_uri = payload.veo_video_ref
240
+ else:
241
+ video_file = await loop.run_in_executor(
242
+ None,
243
+ lambda: client.files.get(name=payload.veo_video_ref),
244
+ )
245
+ video_uri = getattr(video_file, "uri", None) or getattr(
246
+ video_file, "download_uri", None
247
+ )
248
+ if not video_uri:
249
+ raise ValueError(
250
+ "Veo file reference did not include a usable URI. "
251
+ "Use the veo_video_uri value from the reference JSON."
252
+ )
253
+
254
+ config = types.GenerateVideosConfig(
255
+ number_of_videos=1,
256
+ duration_seconds=8,
257
+ resolution="720p",
258
+ )
259
+
260
+ request_kwargs = {
261
+ "model": _VEO_MODEL,
262
+ "video": types.Video(uri=video_uri),
263
+ "config": config,
264
+ }
265
+ if payload.prompt:
266
+ request_kwargs["prompt"] = payload.prompt
267
+
268
+ operation = await loop.run_in_executor(
269
+ None,
270
+ lambda: client.models.generate_videos(**request_kwargs),
271
+ )
272
+
273
+ while not operation.done:
274
+ await asyncio.sleep(10)
275
+ operation = await loop.run_in_executor(
276
+ None,
277
+ lambda: client.operations.get(operation),
278
+ )
279
+
280
+ generated_video = operation.response.generated_videos[0]
281
+ return save_veo_video_with_metadata(
282
+ client,
283
+ generated_video.video,
284
+ self.name,
285
+ self.product_name,
286
+ )
287
+
288
+ def _resolve_endpoint(self, action: str) -> str:
289
+ if action == "edit":
290
+ return "fal-ai/kling-video/o3/standard/video-to-video/edit"
291
+ raise ValueError(f"Unsupported fal.ai action: {action}")
292
+
293
+ def _resolve_media_url(self, value: Optional[str], fal: fal_client.SyncClient) -> str:
294
+ if value is None:
295
+ raise ValueError("Media source is required")
296
+
297
+ if value.startswith("http://") or value.startswith("https://"):
298
+ return value
299
+
300
+ # Try as absolute/relative path first
301
+ path = os.path.expanduser(value)
302
+ if os.path.exists(path):
303
+ return fal.upload_file(path)
304
+
305
+ # Try in product's generated_videos directory
306
+ videos_dir = get_videos_dir(self.product_name)
307
+
308
+ # Try with common video extensions
309
+ for ext in [".mp4", ".mov", ".avi", ".webm"]:
310
+ # Try with extension
311
+ video_path = os.path.join(videos_dir, f"{value}{ext}")
312
+ if os.path.exists(video_path):
313
+ return fal.upload_file(video_path)
314
+
315
+ # Try without adding extension (in case value already has one)
316
+ video_path = os.path.join(videos_dir, value)
317
+ if os.path.exists(video_path):
318
+ return fal.upload_file(video_path)
319
+
320
+ raise FileNotFoundError(
321
+ f"Video file not found: '{value}'\n"
322
+ f" Searched in: {videos_dir}\n"
323
+ f" Also tried as absolute/relative path: {path}"
324
+ )
325
+
326
+ def _extract_video_url(self, result: dict) -> Optional[str]:
327
+ video_info = result.get("video")
328
+ if isinstance(video_info, dict):
329
+ return video_info.get("url")
330
+ return None
331
+
332
+ def _download_file(self, url: str, output_path: str) -> None:
333
+ with httpx.Client(timeout=120.0) as client:
334
+ with client.stream("GET", url) as response:
335
+ response.raise_for_status()
336
+ with open(output_path, "wb") as out_file:
337
+ for chunk in response.iter_bytes():
338
+ if chunk:
339
+ out_file.write(chunk)
340
+
341
+ def _extract_first_frame(self, video_path: str, output_path: str):
342
+ cap = cv2.VideoCapture(video_path)
343
+ ret, frame = cap.read()
344
+ cap.release()
345
+
346
+ if not ret:
347
+ return None
348
+
349
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
350
+ thumbnail_image = Image.fromarray(frame_rgb)
351
+ thumbnail_image.save(output_path)
352
+
353
+ return thumbnail_image
354
+
355
+ if __name__ == "__main__":
356
+ tool = EditVideoContent(
357
+ product_name="Test_Product",
358
+ name="test_video_edit",
359
+ mode=EditMode(
360
+ action="edit",
361
+ video_source="test_video",
362
+ prompt="Replace the dog with a fox",
363
+ ),
364
+ )
365
+ try:
366
+ result = asyncio.run(tool.run())
367
+ print(result)
368
+ except Exception as exc:
369
+ print(f"Video editing failed: {exc}")
@@ -0,0 +1,133 @@
1
+ """Tool for generating images using Google's Gemini 2.5 Flash Image model."""
2
+
3
+ import asyncio
4
+ import os
5
+ from typing import Literal
6
+
7
+ from google import genai
8
+ from pydantic import Field, field_validator
9
+
10
+ from agency_swarm import BaseTool
11
+
12
+
13
+ from .utils.image_utils import (
14
+ get_images_dir,
15
+ MODEL_NAME,
16
+ extract_image_from_response,
17
+ extract_usage_metadata,
18
+ process_variant_result,
19
+ split_results_and_usage,
20
+ run_parallel_variants,
21
+ compress_image_for_base64,
22
+ )
23
+
24
+
25
+ class GenerateImage(BaseTool):
26
+ """Generate images using Google's Gemini 2.5 Flash Image (Nano Banana) model.
27
+
28
+ Images are saved to: mnt/{product_name}/generated_images/
29
+ """
30
+
31
+ product_name: str = Field(
32
+ ...,
33
+ description="Name of the product this image is for (e.g., 'Acme_Widget_Pro', 'Green_Tea_Extract'). Used to organize files into product-specific folders.",
34
+ )
35
+ prompt: str = Field(
36
+ ...,
37
+ description=(
38
+ "The text prompt describing the image to generate. Start with 'Generate an image of' "
39
+ "and describe the image in detail."
40
+ ),
41
+ )
42
+ file_name: str = Field(
43
+ ...,
44
+ description="The name for the generated image file (without extension)",
45
+ )
46
+ num_variants: int = Field(
47
+ default=1,
48
+ description="Number of image variants to generate (1-4, default is 1)",
49
+ )
50
+ aspect_ratio: Literal["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"] = Field(
51
+ default="1:1",
52
+ description="The aspect ratio of the generated image (default is 1:1)",
53
+ )
54
+
55
+ @field_validator("prompt")
56
+ @classmethod
57
+ def _prompt_not_blank(cls, value: str) -> str:
58
+ if not value.strip():
59
+ raise ValueError("prompt must not be empty")
60
+ return value
61
+
62
+ @field_validator("file_name")
63
+ @classmethod
64
+ def _filename_not_blank(cls, value: str) -> str:
65
+ if not value.strip():
66
+ raise ValueError("file_name must not be empty")
67
+ return value
68
+
69
+ @field_validator("num_variants")
70
+ @classmethod
71
+ def _validate_num_variants(cls, value: int) -> int:
72
+ if value < 1 or value > 4:
73
+ raise ValueError("num_variants must be between 1 and 4")
74
+ return value
75
+
76
+ async def run(self) -> list:
77
+ """Generate images using the Gemini API."""
78
+ api_key = os.getenv("GOOGLE_API_KEY")
79
+ if not api_key:
80
+ raise ValueError("GOOGLE_API_KEY is not set. Add it to your .env to use image generation.")
81
+
82
+ client = genai.Client(api_key=api_key)
83
+ images_dir = get_images_dir(self.product_name)
84
+
85
+ def generate_single_variant(variant_num: int):
86
+ try:
87
+ response = client.models.generate_content(
88
+ model=MODEL_NAME,
89
+ contents=[self.prompt],
90
+ config=genai.types.GenerateContentConfig(
91
+ image_config=genai.types.ImageConfig(aspect_ratio=self.aspect_ratio),
92
+ ),
93
+ )
94
+ usage_metadata = extract_usage_metadata(response)
95
+ image, _text = extract_image_from_response(response)
96
+ if image is None:
97
+ return None
98
+ result = process_variant_result(
99
+ variant_num,
100
+ image,
101
+ self.file_name,
102
+ self.num_variants,
103
+ compress_image_for_base64,
104
+ images_dir,
105
+ )
106
+ result["prompt_tokens"] = float(usage_metadata.get("prompt_token_count") or 0)
107
+ result["candidate_tokens"] = float(usage_metadata.get("candidates_token_count") or 0)
108
+ return result
109
+ except Exception:
110
+ return None
111
+
112
+ raw_results = await run_parallel_variants(generate_single_variant, self.num_variants)
113
+ if not raw_results:
114
+ raise RuntimeError("No variants were successfully generated")
115
+
116
+ results, _usage = split_results_and_usage(raw_results)
117
+ return results
118
+
119
+ if __name__ == "__main__":
120
+ # Example usage with Google Gemini 2.5 Flash Image
121
+ tool = GenerateImage(
122
+ product_name="Test_Product",
123
+ prompt=(
124
+ "Generate an image of a sparrow flying away from the camera"
125
+ ),
126
+ file_name="test_image",
127
+ aspect_ratio="16:9",
128
+ )
129
+ try:
130
+ result = asyncio.run(tool.run())
131
+ print(result)
132
+ except Exception as exc:
133
+ print(f"Image generation failed: {exc}")