@_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,233 @@
1
+ """Tool for trimming videos from start and/or end."""
2
+
3
+ import os
4
+ import subprocess
5
+ import asyncio
6
+ import cv2
7
+ from typing import Optional
8
+ from pathlib import Path
9
+
10
+ from pydantic import Field, field_validator, model_validator
11
+ from PIL import Image
12
+
13
+ from agency_swarm import BaseTool, ToolOutputText
14
+
15
+ from .utils.video_utils import (
16
+ get_videos_dir,
17
+ ensure_not_blank,
18
+ generate_spritesheet,
19
+ extract_last_frame,
20
+ create_image_output,
21
+ resolve_ffmpeg_executable,
22
+ )
23
+
24
+
25
+ class TrimVideo(BaseTool):
26
+ """
27
+ Trim a video by removing seconds from the start and/or end.
28
+
29
+ Useful for removing unwanted intro/outro segments or adjusting video length.
30
+
31
+ Videos are saved to: mnt/{product_name}/generated_videos/
32
+ """
33
+
34
+ product_name: str = Field(
35
+ ...,
36
+ description="Name of the product this video is for (e.g., 'Acme_Widget_Pro', 'Green_Tea_Extract'). Used to organize files into product-specific folders.",
37
+ )
38
+ input_video: str = Field(
39
+ ...,
40
+ description=(
41
+ "The video to trim. Can be: "
42
+ "1) Video name without extension (searches generated_videos folder), "
43
+ "2) Full local path to video file."
44
+ ),
45
+ )
46
+ output_name: str = Field(
47
+ ...,
48
+ description="The name for the trimmed video file (without extension)",
49
+ )
50
+ trim_start: Optional[float] = Field(
51
+ default=None,
52
+ description="Seconds to trim from the start of the video (optional, defaults to 0.0 if not provided)",
53
+ )
54
+ trim_end: Optional[float] = Field(
55
+ default=None,
56
+ description="Seconds to trim from the end of the video (optional, defaults to 0.0 if not provided)",
57
+ )
58
+
59
+ @field_validator("input_video")
60
+ @classmethod
61
+ def _input_not_blank(cls, value: str) -> str:
62
+ return ensure_not_blank(value, "input_video")
63
+
64
+ @field_validator("output_name")
65
+ @classmethod
66
+ def _output_not_blank(cls, value: str) -> str:
67
+ return ensure_not_blank(value, "output_name")
68
+
69
+ @model_validator(mode='after')
70
+ def _validate_and_set_defaults(self):
71
+ """Set defaults and validate that at least one trim parameter is provided (> 0)"""
72
+ # Set defaults
73
+ if self.trim_start is None:
74
+ self.trim_start = 0.0
75
+ if self.trim_end is None:
76
+ self.trim_end = 0.0
77
+
78
+ # Validate non-negative
79
+ if self.trim_start < 0:
80
+ raise ValueError("trim_start must be non-negative")
81
+ if self.trim_end < 0:
82
+ raise ValueError("trim_end must be non-negative")
83
+
84
+ # Ensure at least one is provided
85
+ if self.trim_start == 0.0 and self.trim_end == 0.0:
86
+ raise ValueError(
87
+ "At least one of trim_start or trim_end must be greater than 0. "
88
+ "Provide at least one trim value."
89
+ )
90
+
91
+ return self
92
+
93
+ async def run(self) -> list:
94
+ """Trim the video and save with metadata."""
95
+ input_path = self._resolve_video_path()
96
+ videos_dir = get_videos_dir(self.product_name)
97
+ output_path = os.path.join(videos_dir, f"{self.output_name}.mp4")
98
+
99
+ loop = asyncio.get_event_loop()
100
+ await loop.run_in_executor(None, self._trim_video_blocking, input_path, output_path)
101
+
102
+ output = []
103
+
104
+ spritesheet_path = os.path.join(videos_dir, f"{self.output_name}_spritesheet.jpg")
105
+ spritesheet = await loop.run_in_executor(None, generate_spritesheet, output_path, spritesheet_path)
106
+ if spritesheet:
107
+ output.extend(create_image_output(spritesheet_path, f"{self.output_name}_spritesheet.jpg"))
108
+
109
+ thumbnail_path = os.path.join(videos_dir, f"{self.output_name}_thumbnail.jpg")
110
+ thumbnail = await loop.run_in_executor(None, self._extract_first_frame, output_path, thumbnail_path)
111
+ if thumbnail:
112
+ output.extend(create_image_output(thumbnail_path, f"{self.output_name}_thumbnail.jpg"))
113
+
114
+ last_frame_path = os.path.join(videos_dir, f"{self.output_name}_last_frame.jpg")
115
+ last_frame = await loop.run_in_executor(None, extract_last_frame, output_path, last_frame_path)
116
+ if last_frame:
117
+ output.extend(create_image_output(last_frame_path, f"{self.output_name}_last_frame.jpg"))
118
+
119
+ output.append(ToolOutputText(
120
+ type="text",
121
+ text=f"Video trimmed successfully!\nSaved to: `{self.output_name}.mp4`\nPath: {output_path}\nTrimmed: {self.trim_start}s from start, {self.trim_end}s from end"
122
+ ))
123
+
124
+ return output
125
+
126
+ def _resolve_video_path(self) -> str:
127
+ """Resolve input video to full path."""
128
+ # Try as full path first
129
+ path = Path(self.input_video).expanduser().resolve()
130
+
131
+ if path.exists():
132
+ return str(path)
133
+
134
+ # Try as video name without extension in generated_videos
135
+ videos_dir = get_videos_dir(self.product_name)
136
+
137
+ for ext in [".mp4", ".mov", ".avi", ".webm"]:
138
+ potential_path = os.path.join(videos_dir, f"{self.input_video}{ext}")
139
+ if os.path.exists(potential_path):
140
+ return potential_path
141
+
142
+ raise FileNotFoundError(
143
+ f"Video '{self.input_video}' not found in {videos_dir}. "
144
+ f"Tried extensions: .mp4, .mov, .avi, .webm"
145
+ )
146
+
147
+ def _trim_video_blocking(self, input_path: str, output_path: str) -> None:
148
+ """Trim video using ffmpeg (blocking operation)."""
149
+ cap = cv2.VideoCapture(input_path)
150
+ fps = cap.get(cv2.CAP_PROP_FPS)
151
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
152
+ original_duration = total_frames / fps
153
+ cap.release()
154
+
155
+ output_duration = original_duration - self.trim_start - self.trim_end
156
+
157
+ if output_duration <= 0:
158
+ raise ValueError(
159
+ f"Invalid trim parameters: output duration would be {output_duration:.2f}s. "
160
+ f"Video duration is {original_duration:.2f}s. "
161
+ f"Reduce trim_start ({self.trim_start}s) and/or trim_end ({self.trim_end}s)."
162
+ )
163
+
164
+ # Using -ss (start time) and -t (duration) for precise trimming.
165
+ # -c copy would be fastest but may have keyframe issues, so we re-encode with H.264.
166
+ ffmpeg_executable = resolve_ffmpeg_executable()
167
+ ffmpeg_cmd = [
168
+ ffmpeg_executable,
169
+ "-y", # Overwrite output file if it exists
170
+ "-i", input_path, # Input file
171
+ "-ss", str(self.trim_start), # Start time
172
+ "-t", str(output_duration), # Duration
173
+ "-c:v", "libx264", # Video codec: H.264
174
+ "-preset", "medium", # Encoding preset (balance speed/quality)
175
+ "-crf", "23", # Constant Rate Factor (quality: 0-51, lower is better)
176
+ "-c:a", "aac", # Audio codec
177
+ "-b:a", "128k", # Audio bitrate
178
+ "-movflags", "+faststart", # Enable fast start for web playback
179
+ "-pix_fmt", "yuv420p", # Pixel format for compatibility
180
+ output_path
181
+ ]
182
+
183
+ try:
184
+ subprocess.run(
185
+ ffmpeg_cmd,
186
+ stdout=subprocess.PIPE,
187
+ stderr=subprocess.PIPE,
188
+ text=True,
189
+ check=True
190
+ )
191
+ except subprocess.CalledProcessError as e:
192
+ raise RuntimeError(
193
+ f"ffmpeg failed to trim video. Error: {e.stderr}"
194
+ )
195
+ except FileNotFoundError:
196
+ raise RuntimeError(
197
+ "ffmpeg not found. Please install ffmpeg and ensure it's in your PATH. "
198
+ "Download from: https://ffmpeg.org/download.html"
199
+ )
200
+
201
+ def _extract_first_frame(self, video_path: str, output_path: str) -> Optional[object]:
202
+ """Extract the first frame from video as thumbnail."""
203
+ cap = cv2.VideoCapture(video_path)
204
+ ret, frame = cap.read()
205
+ cap.release()
206
+
207
+ if not ret:
208
+ return None
209
+
210
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
211
+ thumbnail_image = Image.fromarray(frame_rgb)
212
+ thumbnail_image.save(output_path)
213
+
214
+ return thumbnail_image
215
+
216
+
217
+ if __name__ == "__main__":
218
+ # Example: Trim only from start (trim_end defaults to 0.0)
219
+ tool = TrimVideo(
220
+ product_name="Test_Product",
221
+ input_video="test_video", # Will look for test_video.mp4 in generated_videos
222
+ output_name="test_video_trimmed",
223
+ # trim_start=1.0, # Trim 1 second from start
224
+ trim_end=1.0
225
+ )
226
+
227
+ try:
228
+ result = asyncio.run(tool.run())
229
+ print("\nTrim complete!")
230
+ print(result)
231
+ except Exception as exc:
232
+ print(f"Video trim failed: {exc}")
233
+
@@ -0,0 +1 @@
1
+ """Tools for the video generation agent."""
@@ -0,0 +1 @@
1
+ """Utility helpers for video generation tools."""
@@ -0,0 +1,174 @@
1
+ import os
2
+ import io
3
+ import base64
4
+ import logging
5
+ from pathlib import Path
6
+ import asyncio
7
+ from PIL import Image
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ MODEL_NAME = "gemini-2.5-flash-image"
12
+
13
+ if os.path.isfile("/.dockerenv"):
14
+ MNT_DIR = Path("/app/mnt")
15
+ else:
16
+ MNT_DIR = Path(__file__).parent.parent.parent.parent / "mnt"
17
+
18
+ IMAGES_DIR = str(MNT_DIR / "generated_images")
19
+
20
+ OUTPUT_FORMAT = "png"
21
+
22
+
23
+ def get_images_dir(product_name: str) -> str:
24
+ """Return (and create) the images directory for a specific product."""
25
+ images_dir = MNT_DIR / product_name / "generated_images"
26
+ images_dir.mkdir(parents=True, exist_ok=True)
27
+ return str(images_dir)
28
+
29
+
30
+ def create_filename(file_name, variant_num, num_variants, output_format):
31
+ if num_variants == 1:
32
+ image_name = file_name
33
+ else:
34
+ image_name = f"{file_name}_variant_{variant_num}"
35
+ filename = f"{image_name}.{output_format}"
36
+ return image_name, filename
37
+
38
+
39
+ def load_image_by_name(image_name, images_dir, extensions=None):
40
+ """Load an image by name, trying common extensions in order."""
41
+ if extensions is None:
42
+ extensions = ['.png', '.jpg', '.jpeg', '.webp']
43
+
44
+ for ext in extensions:
45
+ potential_path = os.path.join(images_dir, f"{image_name}{ext}")
46
+ if os.path.exists(potential_path):
47
+ try:
48
+ image = Image.open(potential_path)
49
+ return image, potential_path, None
50
+ except Exception as e:
51
+ return None, None, f"Error loading image {potential_path}: {str(e)}"
52
+
53
+ return None, None, f"Error: Image file not found: {image_name} (tried {', '.join(extensions)})"
54
+
55
+
56
+ def extract_image_from_response(response):
57
+ """Extract the first image and any text from a Gemini API response."""
58
+ image = None
59
+ text_output = ""
60
+
61
+ for part in response.candidates[0].content.parts:
62
+ if part.text is not None:
63
+ text_output += part.text
64
+ elif part.inline_data is not None:
65
+ image = Image.open(io.BytesIO(part.inline_data.data))
66
+
67
+ return image, text_output
68
+
69
+
70
+ def extract_image_parts_from_response(response):
71
+ """Extract raw image bytes from a Gemini API response."""
72
+ return [
73
+ part.inline_data.data
74
+ for part in response.candidates[0].content.parts
75
+ if part.inline_data
76
+ ]
77
+
78
+
79
+ def extract_usage_metadata(response):
80
+ usage_metadata = getattr(response, "usage_metadata", {}) or {}
81
+ if usage_metadata and not isinstance(usage_metadata, dict):
82
+ if hasattr(usage_metadata, "model_dump"):
83
+ usage_metadata = usage_metadata.model_dump()
84
+ elif hasattr(usage_metadata, "__dict__"):
85
+ usage_metadata = vars(usage_metadata)
86
+ else:
87
+ try:
88
+ usage_metadata = dict(usage_metadata)
89
+ except (TypeError, ValueError):
90
+ usage_metadata = {}
91
+ return usage_metadata
92
+
93
+
94
+ def split_results_and_usage(raw_results):
95
+ results = []
96
+ total_prompt_tokens = 0.0
97
+ total_candidate_tokens = 0.0
98
+
99
+ for item in raw_results:
100
+ result = dict(item)
101
+ total_prompt_tokens += float(result.pop("prompt_tokens", 0.0) or 0.0)
102
+ total_candidate_tokens += float(result.pop("candidate_tokens", 0.0) or 0.0)
103
+ results.append(result)
104
+
105
+ usage_metadata = {
106
+ "prompt_token_count": total_prompt_tokens,
107
+ "candidates_token_count": total_candidate_tokens,
108
+ }
109
+ return results, usage_metadata
110
+
111
+
112
+ def process_variant_result(variant_num, image, file_name, num_variants, compress_func, images_dir=None):
113
+ """Save a variant image and return its result dict."""
114
+ save_dir = images_dir if images_dir is not None else IMAGES_DIR
115
+ image_name, filename = create_filename(file_name, variant_num, num_variants, OUTPUT_FORMAT)
116
+ filepath = os.path.join(save_dir, filename)
117
+ image.save(filepath, OUTPUT_FORMAT)
118
+ compressed_b64 = compress_func(image)
119
+ return {
120
+ "variant": variant_num,
121
+ "file_path": filepath,
122
+ "image_name": image_name,
123
+ "base64": compressed_b64,
124
+ }
125
+
126
+
127
+ async def run_parallel_variants(variant_func, num_variants):
128
+ """Run variant_func for each variant concurrently in a thread pool."""
129
+ loop = asyncio.get_event_loop()
130
+ tasks = [loop.run_in_executor(None, variant_func, i + 1) for i in range(num_variants)]
131
+ completed = await asyncio.gather(*tasks, return_exceptions=True)
132
+ return [r for r in completed if r is not None and not isinstance(r, Exception)]
133
+
134
+
135
+ def compress_image_for_base64(image: Image.Image, max_size: int = 1024) -> str:
136
+ """Resize and JPEG-compress an image, returning a base64-encoded string."""
137
+ if image.mode in ("RGBA", "P"):
138
+ image = image.convert("RGB")
139
+
140
+ width, height = image.size
141
+ if max(width, height) > max_size:
142
+ if width > height:
143
+ new_width = max_size
144
+ new_height = int(height * (max_size / width))
145
+ else:
146
+ new_height = max_size
147
+ new_width = int(width * (max_size / height))
148
+ image = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
149
+
150
+ buffer = io.BytesIO()
151
+ image.save(buffer, format="JPEG", quality=85)
152
+ return base64.b64encode(buffer.getvalue()).decode()
153
+
154
+
155
+ def combine_image_parts(image_parts):
156
+ """Combine multiple raw image parts into a single horizontally-stitched image."""
157
+ if not image_parts:
158
+ return None
159
+
160
+ images = [Image.open(io.BytesIO(part)) for part in image_parts]
161
+
162
+ if len(images) == 1:
163
+ return images[0]
164
+
165
+ total_width = sum(img.width for img in images)
166
+ max_height = max(img.height for img in images)
167
+ combined = Image.new('RGB', (total_width, max_height))
168
+
169
+ x_offset = 0
170
+ for img in images:
171
+ combined.paste(img, (x_offset, 0))
172
+ x_offset += img.width
173
+
174
+ return combined