@_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,522 @@
1
+ """Shared utilities for Sora video tools."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import io
6
+ import json
7
+ import logging
8
+ import os
9
+ import shutil
10
+ from pathlib import Path
11
+ from typing import Optional
12
+ from urllib.parse import urlparse
13
+
14
+ import cv2
15
+ import httpx
16
+ from openai import OpenAI
17
+ from PIL import Image
18
+ from google import genai
19
+
20
+ from agency_swarm import ToolOutputText, ToolOutputImage
21
+
22
+ from .image_utils import (
23
+ load_image_by_name,
24
+ get_images_dir,
25
+ compress_image_for_base64,
26
+ IMAGES_DIR,
27
+ )
28
+
29
+ logger = logging.getLogger(__name__)
30
+
31
+
32
+ SORA_MODEL = "sora-2"
33
+
34
+
35
+ def is_veo_model(model: str) -> bool:
36
+ return model.startswith("veo-")
37
+
38
+
39
+ def is_sora_model(model: str) -> bool:
40
+ return model.startswith("sora-")
41
+
42
+
43
+ def is_seedance_model(model: str) -> bool:
44
+ return model.startswith("seedance-")
45
+
46
+
47
+ if os.path.isfile("/.dockerenv"):
48
+ MNT_DIR = Path("/app/mnt")
49
+ else:
50
+ MNT_DIR = Path(__file__).parent.parent.parent.parent / "mnt"
51
+
52
+ VIDEO_DIR = str(MNT_DIR / "generated_videos") # fallback when no product_name is given
53
+
54
+
55
+ def get_videos_dir(product_name: str) -> str:
56
+ """
57
+ Get the videos directory for a specific product.
58
+
59
+ Args:
60
+ product_name: Name of the product (sanitized folder name)
61
+
62
+ Returns:
63
+ Path to product's generated_videos directory
64
+ """
65
+ videos_dir = MNT_DIR / product_name / "generated_videos"
66
+ videos_dir.mkdir(parents=True, exist_ok=True)
67
+ return str(videos_dir)
68
+
69
+
70
+ def resolve_ffmpeg_executable() -> str:
71
+ """Resolve an ffmpeg executable from PATH or imageio-ffmpeg fallback."""
72
+ ffmpeg_path = shutil.which("ffmpeg")
73
+ if ffmpeg_path:
74
+ return ffmpeg_path
75
+
76
+ try:
77
+ from imageio_ffmpeg import get_ffmpeg_exe # type: ignore
78
+
79
+ ffmpeg_path = get_ffmpeg_exe()
80
+ if ffmpeg_path:
81
+ return ffmpeg_path
82
+ except Exception:
83
+ pass
84
+
85
+ raise RuntimeError(
86
+ "ffmpeg executable not found. Install ffmpeg and add it to PATH, "
87
+ "or install the Python package 'imageio-ffmpeg' for bundled ffmpeg fallback."
88
+ )
89
+
90
+
91
+ def get_openai_client() -> OpenAI:
92
+ """Instantiate an OpenAI client from the environment."""
93
+ api_key = os.getenv("OPENAI_API_KEY")
94
+ if not api_key:
95
+ raise RuntimeError(
96
+ "OPENAI_API_KEY environment variable is required for video operations"
97
+ )
98
+ return OpenAI(api_key=api_key)
99
+
100
+
101
+ def get_gemini_client():
102
+ """Instantiate a Gemini client from the environment."""
103
+ api_key = os.getenv("GOOGLE_API_KEY")
104
+ if not api_key:
105
+ raise ValueError("GOOGLE_API_KEY is not set. Add it to your .env to use video generation.")
106
+ return genai.Client(api_key=api_key)
107
+
108
+
109
+ def parse_video_size(size: str) -> tuple[int, int]:
110
+ """
111
+ Parse video size string into width and height tuple.
112
+
113
+ Args:
114
+ size: Size string in WIDTHxHEIGHT format (e.g. '1280x720')
115
+
116
+ Returns:
117
+ Tuple of (width, height)
118
+ """
119
+ parts = size.lower().split("x")
120
+ if len(parts) != 2:
121
+ raise ValueError(f"Invalid size format: {size}")
122
+ return int(parts[0]), int(parts[1])
123
+
124
+
125
+ def resize_image_to_dimensions(image: Image.Image, width: int, height: int) -> Image.Image:
126
+ """
127
+ Resize an image to match specific dimensions while maintaining aspect ratio.
128
+
129
+ Args:
130
+ image: PIL Image to resize
131
+ width: Target width
132
+ height: Target height
133
+
134
+ Returns:
135
+ Resized PIL Image
136
+ """
137
+ # Calculate aspect ratios
138
+ target_ratio = width / height
139
+ image_ratio = image.width / image.height
140
+
141
+ if abs(target_ratio - image_ratio) < 0.01:
142
+ # Aspect ratios are close enough, just resize directly
143
+ return image.resize((width, height), Image.Resampling.LANCZOS)
144
+
145
+ # Aspect ratios differ, crop to match target ratio first
146
+ if image_ratio > target_ratio:
147
+ # Image is wider than target, crop width
148
+ new_width = int(image.height * target_ratio)
149
+ left = (image.width - new_width) // 2
150
+ image = image.crop((left, 0, left + new_width, image.height))
151
+ else:
152
+ # Image is taller than target, crop height
153
+ new_height = int(image.width / target_ratio)
154
+ top = (image.height - new_height) // 2
155
+ image = image.crop((0, top, image.width, top + new_height))
156
+
157
+ # Now resize to exact dimensions
158
+ return image.resize((width, height), Image.Resampling.LANCZOS)
159
+
160
+
161
+ def resolve_input_reference(reference: Optional[str], target_size: Optional[str] = None, product_name: Optional[str] = None) -> Optional[io.BufferedReader]:
162
+ """
163
+ Turn an image name, local path, or HTTPS URL into a binary file handle for the API.
164
+ Optionally resizes the image to match target video dimensions.
165
+
166
+ Args:
167
+ reference: Image name (without extension), full path, or URL to the reference image
168
+ target_size: Optional target size in WIDTHxHEIGHT format (e.g. '1280x720')
169
+ product_name: Product name for locating images in product-specific folders
170
+
171
+ Returns:
172
+ Binary file handle ready for API upload
173
+ """
174
+ if reference is None:
175
+ return None
176
+
177
+ parsed = urlparse(reference)
178
+
179
+ if parsed.scheme in ("http", "https"):
180
+ # Handle URL
181
+ logger.info("Downloading reference image from URL...")
182
+ with httpx.Client(timeout=30.0) as client:
183
+ response = client.get(reference)
184
+ response.raise_for_status()
185
+ image_data = io.BytesIO(response.content)
186
+ filename = Path(parsed.path).name or "reference.png"
187
+ else:
188
+ # Try as full path first
189
+ path = Path(reference).expanduser().resolve()
190
+
191
+ if path.exists():
192
+ # Handle full path
193
+ logger.info(f"Loading reference image from {path}...")
194
+ with open(path, "rb") as f:
195
+ image_data = io.BytesIO(f.read())
196
+ filename = path.name
197
+ else:
198
+ # Try as image name without extension in multiple directories
199
+ pil_image = None
200
+ image_path = None
201
+
202
+ # Get product-specific directories
203
+ if product_name:
204
+ images_dir = get_images_dir(product_name)
205
+ videos_dir = get_videos_dir(product_name)
206
+ else:
207
+ # Fallback to legacy paths if no product_name provided
208
+ images_dir = IMAGES_DIR
209
+ videos_dir = VIDEO_DIR
210
+
211
+ # Try in generated_images directory first
212
+ logger.info(f"Looking for image '{reference}' in {images_dir}...")
213
+ pil_image, image_path, load_error_images = load_image_by_name(
214
+ reference, images_dir, [".png", ".jpg", ".jpeg", ".webp"]
215
+ )
216
+
217
+ # If not found, try in generated_videos directory (for thumbnails/spritesheets)
218
+ if load_error_images:
219
+ logger.info(f"Not found in {images_dir}, trying {videos_dir}...")
220
+ pil_image, image_path, load_error_videos = load_image_by_name(
221
+ reference, videos_dir, [".png", ".jpg", ".jpeg", ".webp"]
222
+ )
223
+
224
+ if pil_image is None:
225
+ raise FileNotFoundError(f"Reference image '{reference}' not found in {images_dir} or {videos_dir}")
226
+
227
+ logger.info(f"Loaded image: {image_path}")
228
+
229
+ # Convert PIL Image to BytesIO
230
+ image_data = io.BytesIO()
231
+ pil_image.save(image_data, format=pil_image.format or "PNG")
232
+ image_data.seek(0)
233
+ filename = Path(image_path).name
234
+
235
+ if target_size:
236
+ logger.info(f"Resizing reference image to match video dimensions: {target_size}")
237
+ image_data.seek(0)
238
+ image = Image.open(image_data)
239
+
240
+ # Get target dimensions
241
+ width, height = parse_video_size(target_size)
242
+
243
+ # Resize the image
244
+ resized_image = resize_image_to_dimensions(image, width, height)
245
+
246
+ # Save resized image to buffer
247
+ buffer = io.BytesIO()
248
+ # Preserve format or use PNG as default
249
+ image_format = image.format or "PNG"
250
+ resized_image.save(buffer, format=image_format)
251
+ buffer.seek(0)
252
+ buffer.name = filename
253
+
254
+ logger.info(f"Reference image resized from {image.width}x{image.height} to {width}x{height}")
255
+ return buffer # type: ignore[return-value]
256
+
257
+ image_data.seek(0)
258
+ image_data.name = filename
259
+ return image_data # type: ignore[return-value]
260
+
261
+
262
+ def validate_resolution(value: Optional[str]) -> Optional[str]:
263
+ """Ensure a resolution string is in WIDTHxHEIGHT format."""
264
+
265
+ if value is None:
266
+ return None
267
+ parts = value.lower().split("x")
268
+ if len(parts) != 2 or not all(part.isdigit() for part in parts):
269
+ raise ValueError("size must be formatted as WIDTHxHEIGHT (e.g. 1280x720)")
270
+ return value
271
+
272
+
273
+ def ensure_not_blank(value: str, field_name: str) -> str:
274
+ """Raise if a text field is empty or whitespace only."""
275
+
276
+ if not value.strip():
277
+ raise ValueError(f"{field_name} must not be empty")
278
+ return value
279
+
280
+
281
+ def download_video_variant(client: OpenAI, video_id: str, variant: str, output_path: str) -> None:
282
+ """
283
+ Download a specific variant of a video from Sora API.
284
+
285
+ Args:
286
+ client: OpenAI client instance
287
+ video_id: The video ID from Sora API
288
+ variant: Type of content to download (spritesheet, thumbnail, or video)
289
+ output_path: Full path where the file should be saved
290
+ """
291
+ logger.info(f"Downloading {variant} for video {video_id}...")
292
+ content = client.videos.download_content(video_id, variant=variant)
293
+ content.write_to_file(output_path)
294
+
295
+
296
+ def create_image_output(image_path: str, label: str) -> list:
297
+ """
298
+ Create tool output objects for an image file.
299
+
300
+ Args:
301
+ image_path: Path to the image file
302
+ label: Label to display for the image (filename)
303
+
304
+ Returns:
305
+ List containing ToolOutputText and ToolOutputImage objects
306
+ """
307
+ image = Image.open(image_path)
308
+ compressed_b64 = compress_image_for_base64(image)
309
+
310
+ return [
311
+ ToolOutputText(type="text", text=f"{label}\nPath: {image_path}"),
312
+ ToolOutputImage(type="image", image_url=f"data:image/png;base64,{compressed_b64}", detail="auto")
313
+ ]
314
+
315
+
316
+ def extract_last_frame(video_path: str, output_path: str) -> Optional[Image.Image]:
317
+ """
318
+ Extract the last frame from a video file.
319
+
320
+ Args:
321
+ video_path: Path to the video file
322
+ output_path: Path where the last frame image should be saved
323
+
324
+ Returns:
325
+ PIL Image object of the last frame, or None if extraction failed
326
+ """
327
+ logger.info("Extracting last frame from video...")
328
+ cap = cv2.VideoCapture(video_path)
329
+
330
+ # Get total frame count and set to last frame
331
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
332
+ cap.set(cv2.CAP_PROP_POS_FRAMES, total_frames - 1)
333
+ ret, frame = cap.read()
334
+
335
+ cap.release()
336
+
337
+ if not ret:
338
+ return None
339
+
340
+ # Convert BGR to RGB (OpenCV uses BGR)
341
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
342
+ last_frame_image = Image.fromarray(frame_rgb)
343
+
344
+ # Save last frame
345
+ last_frame_image.save(output_path)
346
+
347
+ return last_frame_image
348
+
349
+
350
+ def generate_spritesheet(video_path: str, output_path: str, frames_per_row: int = 6, num_rows: int = 1) -> Optional[Image.Image]:
351
+ """
352
+ Generate a linear spritesheet from a video file.
353
+
354
+ Args:
355
+ video_path: Path to the video file
356
+ output_path: Path where the spritesheet should be saved
357
+ frames_per_row: Number of frames in the spritesheet (default 6, range 4-7)
358
+ num_rows: Number of rows (default 1 for linear layout)
359
+
360
+ Returns:
361
+ PIL Image object of the spritesheet, or None if generation failed
362
+ """
363
+ logger.info("Generating spritesheet from video...")
364
+ cap = cv2.VideoCapture(video_path)
365
+
366
+ # Get total frame count
367
+ total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
368
+ frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
369
+ frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
370
+
371
+ # Calculate frames to extract (evenly distributed)
372
+ total_frames_needed = frames_per_row * num_rows
373
+ frame_indices = [int(i * total_frames / total_frames_needed) for i in range(total_frames_needed)]
374
+
375
+ # Extract frames
376
+ frames = []
377
+ for frame_idx in frame_indices:
378
+ cap.set(cv2.CAP_PROP_POS_FRAMES, frame_idx)
379
+ ret, frame = cap.read()
380
+ if ret:
381
+ # Convert BGR to RGB
382
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
383
+ frames.append(Image.fromarray(frame_rgb))
384
+
385
+ cap.release()
386
+
387
+ if not frames:
388
+ return None
389
+
390
+ # Calculate thumbnail size (smaller for spritesheet)
391
+ thumb_width = frame_width // 4
392
+ thumb_height = frame_height // 4
393
+
394
+ # Create spritesheet
395
+ spritesheet_width = thumb_width * frames_per_row
396
+ spritesheet_height = thumb_height * num_rows
397
+ spritesheet = Image.new('RGB', (spritesheet_width, spritesheet_height))
398
+
399
+ # Paste frames into spritesheet
400
+ for idx, frame in enumerate(frames):
401
+ row = idx // frames_per_row
402
+ col = idx % frames_per_row
403
+ x = col * thumb_width
404
+ y = row * thumb_height
405
+
406
+ # Resize frame to thumbnail size
407
+ frame_thumb = frame.resize((thumb_width, thumb_height), Image.Resampling.LANCZOS)
408
+ spritesheet.paste(frame_thumb, (x, y))
409
+
410
+ # Save spritesheet
411
+ spritesheet.save(output_path, quality=85)
412
+ logger.info(f"Spritesheet saved to {output_path}")
413
+
414
+ return spritesheet
415
+
416
+
417
+ def download_veo_video(gemini_client, video_file, output_path: str) -> None:
418
+ """
419
+ Download a Veo video from Google Gemini API.
420
+
421
+ Args:
422
+ gemini_client: Google Gemini client instance
423
+ video_file: Video file object from Gemini API
424
+ output_path: Full path where the video should be saved
425
+ """
426
+ logger.info(f"Downloading Veo video to {output_path}...")
427
+ gemini_client.files.download(file=video_file)
428
+ video_file.save(output_path)
429
+
430
+
431
+ def save_veo_video_with_metadata(gemini_client, video_file, name: str, product_name: str) -> list:
432
+ """
433
+ Download and save Veo video with metadata (spritesheet, thumbnail, last frame).
434
+
435
+ Args:
436
+ gemini_client: Google Gemini client instance
437
+ video_file: Video file object from Gemini API
438
+ name: Base name for saved files (without extension)
439
+ product_name: Name of the product (for organizing files in product-specific folders)
440
+
441
+ Returns:
442
+ List of ToolOutput objects showing the saved files
443
+ """
444
+ output = []
445
+ videos_dir = get_videos_dir(product_name)
446
+
447
+ video_path = os.path.join(videos_dir, f"{name}.mp4")
448
+ download_veo_video(gemini_client, video_file, video_path)
449
+
450
+ spritesheet_path = os.path.join(videos_dir, f"{name}_spritesheet.jpg")
451
+ generate_spritesheet(video_path, spritesheet_path)
452
+
453
+ thumbnail_path = os.path.join(videos_dir, f"{name}_thumbnail.jpg")
454
+ cap = cv2.VideoCapture(video_path)
455
+ ret, frame = cap.read()
456
+ if ret:
457
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
458
+ Image.fromarray(frame_rgb).save(thumbnail_path)
459
+ cap.release()
460
+
461
+ last_frame_path = os.path.join(videos_dir, f"{name}_last_frame.jpg")
462
+ extract_last_frame(video_path, last_frame_path)
463
+
464
+ veo_reference = {}
465
+ if getattr(video_file, "name", None):
466
+ veo_reference["veo_video_ref"] = video_file.name
467
+ if getattr(video_file, "uri", None):
468
+ veo_reference["veo_video_uri"] = video_file.uri
469
+
470
+ reference_path = None
471
+ if veo_reference:
472
+ reference_path = os.path.join(videos_dir, f"{name}_veo_reference.json")
473
+ with open(reference_path, "w", encoding="utf-8") as handle:
474
+ json.dump(veo_reference, handle, indent=2, ensure_ascii=True)
475
+
476
+ summary_lines = [
477
+ f"Video saved to `{name}.mp4`",
478
+ f"Path: {video_path}",
479
+ ]
480
+ if veo_reference.get("veo_video_ref"):
481
+ summary_lines.append(f"Veo reference: {veo_reference['veo_video_ref']}")
482
+ if veo_reference.get("veo_video_uri"):
483
+ summary_lines.append(f"Veo URI: {veo_reference['veo_video_uri']}")
484
+ if reference_path:
485
+ summary_lines.append(f"Reference file: {reference_path}")
486
+
487
+ output.append(ToolOutputText(type="text", text="\n".join(summary_lines)))
488
+
489
+ return output
490
+
491
+
492
+ def save_video_with_metadata(client: OpenAI, video_id: str, name: str, product_name: str) -> list:
493
+ """
494
+ Download and save video with all metadata (spritesheet, thumbnail, last frame).
495
+
496
+ Args:
497
+ client: OpenAI client instance
498
+ video_id: The video ID from Sora API
499
+ name: Base name for saved files (without extension)
500
+ product_name: Name of the product (for organizing files in product-specific folders)
501
+
502
+ Returns:
503
+ List of ToolOutput objects showing the saved files
504
+ """
505
+ output = []
506
+ videos_dir = get_videos_dir(product_name)
507
+
508
+ spritesheet_path = os.path.join(videos_dir, f"{name}_spritesheet.jpg")
509
+ download_video_variant(client, video_id, "spritesheet", spritesheet_path)
510
+
511
+ thumbnail_path = os.path.join(videos_dir, f"{name}_thumbnail.jpg")
512
+ download_video_variant(client, video_id, "thumbnail", thumbnail_path)
513
+
514
+ video_path = os.path.join(videos_dir, f"{name}.mp4")
515
+ download_video_variant(client, video_id, "video", video_path)
516
+
517
+ last_frame_path = os.path.join(videos_dir, f"{name}_last_frame.jpg")
518
+ extract_last_frame(video_path, last_frame_path)
519
+
520
+ output.append(ToolOutputText(type="text", text=f"Video saved to `{name}.mp4`\nPath: {video_path}\nVideo ID: {video_id}"))
521
+
522
+ return output
@@ -0,0 +1,26 @@
1
+ from agency_swarm import Agent, ModelSettings
2
+ from agency_swarm.tools import LoadFileAttachment
3
+ from openai.types.shared.reasoning import Reasoning
4
+
5
+ from config import get_default_model, is_openai_provider
6
+
7
+
8
+ def create_video_generation_agent() -> Agent:
9
+ return Agent(
10
+ name="Video Agent",
11
+ description="A general-purpose agent for video generation and editing.",
12
+ instructions="instructions.md",
13
+ tools_folder="./tools",
14
+ tools=[LoadFileAttachment],
15
+ model=get_default_model(),
16
+ model_settings=ModelSettings(
17
+ reasoning=Reasoning(summary="auto", effort="medium") if is_openai_provider() else None,
18
+ truncation="auto",
19
+ ),
20
+ conversation_starters=[
21
+ "Generate a short promo video for my product launch.",
22
+ "Create an animated explainer video about how AI works.",
23
+ "Edit this video clip and add captions.",
24
+ "Turn my blog post into a video with voiceover.",
25
+ ],
26
+ )
@@ -0,0 +1 @@
1
+ from .virtual_assistant import create_virtual_assistant