@_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,323 @@
1
+ """Convert documents to different formats (PDF, Markdown, TXT)."""
2
+
3
+ from pathlib import Path
4
+ from typing import Literal
5
+
6
+ import html2text
7
+ from agency_swarm.tools import BaseTool, ToolOutputText, tool_output_file_from_path
8
+ from bs4 import BeautifulSoup
9
+ from pydantic import Field
10
+ from weasyprint import HTML
11
+
12
+ from .CreateDocument import CreateDocument
13
+ from .utils.html_docx_core import html_to_docx
14
+ from .utils.html_docx_images import embed_local_images
15
+ from .utils.html_docx_playwright import auto_page_breaks
16
+
17
+ # Base directory for all document files
18
+ from .utils.doc_file_utils import get_project_dir, next_docx_version
19
+
20
+ # Characters that PDF fonts commonly lack glyphs for.
21
+ # Includes both proper Unicode typographic chars and ASCII control-char
22
+ # corruptions that sometimes appear when the LLM emits smart-quote/dash
23
+ # codepoints that get truncated to their low byte during serialisation.
24
+ _UNICODE_TO_ASCII = str.maketrans({
25
+ "\u2018": "'", # ' left single quotation mark
26
+ "\u2019": "'", # ' right single quotation mark / apostrophe
27
+ "\u201c": '"', # " left double quotation mark
28
+ "\u201d": '"', # " right double quotation mark
29
+ "\u2013": "-", # – en dash
30
+ "\u2014": "--", # — em dash
31
+ "\u2026": "...", # … horizontal ellipsis
32
+ "\u00a0": " ", # non-breaking space
33
+ # Corrupted forms: low-byte of U+2019 / U+2013 stored as control chars
34
+ "\x19": "'", # truncated U+2019 right-single-quote low byte
35
+ "\x11": "-", # truncated U+2011/U+2013 dash low byte
36
+ "\x18": "'", # truncated U+2018 left-single-quote low byte
37
+ "\x1c": '"', # truncated U+201C left-double-quote low byte
38
+ "\x1d": '"', # truncated U+201D right-double-quote low byte
39
+ "\x14": "--", # truncated U+2014 em-dash low byte
40
+ })
41
+
42
+
43
+ def _normalize_unicode(html: str) -> str:
44
+ return html.translate(_UNICODE_TO_ASCII)
45
+
46
+
47
+ class ConvertDocument(BaseTool):
48
+ """
49
+ Convert a document to different formats.
50
+
51
+ Supported conversions:
52
+ - HTML → PDF (high-quality, print-ready)
53
+ - HTML → DOCX (Word document)
54
+ - HTML → Markdown (for documentation)
55
+ - HTML → TXT (plain text)
56
+
57
+ The tool reads the .source.html file and converts it to the requested format.
58
+ The original files are preserved - conversion creates a new file.
59
+
60
+ Use this tool to:
61
+ - Create PDF versions for sharing/printing
62
+ - Export to Markdown for documentation sites
63
+ - Generate plain text versions
64
+ """
65
+
66
+ project_name: str = Field(
67
+ ...,
68
+ description="Name of the project folder containing the document"
69
+ )
70
+
71
+ document_name: str = Field(
72
+ ...,
73
+ description="Name of the document to convert (without extension)"
74
+ )
75
+
76
+ output_format: Literal["pdf", "docx", "markdown", "txt"] = Field(
77
+ ...,
78
+ description="""Target format for conversion:
79
+ - 'pdf': High-quality PDF (requires weasyprint)
80
+ - 'docx': Word document
81
+ - 'markdown': Markdown format (useful for documentation)
82
+ - 'txt': Plain text (strips all formatting)"""
83
+ )
84
+
85
+ overwrite: bool = Field(
86
+ default=True,
87
+ description="If True (default), overwrites existing converted file. If False, returns error if file exists."
88
+ )
89
+
90
+ def run(self):
91
+ """Convert document to specified format."""
92
+ try:
93
+ project_dir = get_project_dir(self.project_name)
94
+
95
+ if not project_dir.exists():
96
+ return f"Error: Project '{self.project_name}' not found."
97
+
98
+ doc_name = (
99
+ self.document_name.replace(".html", "")
100
+ .replace(".docx", "")
101
+ .replace(".md", "")
102
+ )
103
+ source_path = project_dir / f"{doc_name}.source.html"
104
+
105
+ if not source_path.exists():
106
+ return f"Error: Document '{doc_name}' not found in project '{self.project_name}'."
107
+
108
+ # Determine output file extension
109
+ ext_map = {
110
+ "pdf": ".pdf",
111
+ "docx": ".docx",
112
+ "markdown": ".md",
113
+ "txt": ".txt",
114
+ }
115
+ output_path = project_dir / f"{doc_name}{ext_map[self.output_format]}"
116
+
117
+ # DOCX auto-versions; all other formats respect overwrite flag
118
+ if self.output_format == "docx":
119
+ output_path = next_docx_version(output_path)
120
+ elif output_path.exists() and not self.overwrite:
121
+ return (
122
+ f"Error: Output file '{output_path.name}' already exists. "
123
+ "Set overwrite=True to replace it."
124
+ )
125
+
126
+ html_content = source_path.read_text(encoding="utf-8")
127
+ html_content = embed_local_images(html_content, project_dir)
128
+ if self.output_format in ("pdf", "docx"):
129
+ html_content = auto_page_breaks(html_content)
130
+
131
+ if self.output_format == "pdf":
132
+ self._convert_to_pdf(html_content, output_path)
133
+ elif self.output_format == "docx":
134
+ self._convert_to_docx(html_content, output_path)
135
+ elif self.output_format == "markdown":
136
+ self._convert_to_markdown(html_content, output_path)
137
+ elif self.output_format == "txt":
138
+ self._convert_to_txt(html_content, output_path)
139
+
140
+ if not output_path.exists():
141
+ return f"Error: Conversion failed to produce '{output_path.name}'."
142
+
143
+ # For DOCX exports, save a snapshot of the HTML source alongside the file.
144
+ # This is the version history — RestoreDocument can roll back to any snapshot.
145
+ if self.output_format == "docx":
146
+ snapshot_path = output_path.parent / f"{output_path.name}.snapshot.html"
147
+ snapshot_path.write_text(source_path.read_text(encoding="utf-8"), encoding="utf-8")
148
+
149
+ output_size = output_path.stat().st_size
150
+
151
+ message = f"""Successfully converted document to {self.output_format.upper()}!
152
+
153
+ Project: {self.project_name}
154
+ Document: {doc_name}
155
+ Source: {source_path.name}
156
+ Output: {output_path.name} ({output_size:,} bytes)
157
+
158
+ Path: {output_path}"""
159
+
160
+ if self.output_format == "pdf":
161
+ return [
162
+ ToolOutputText(text=message),
163
+ tool_output_file_from_path(output_path),
164
+ ]
165
+
166
+ return message
167
+ except Exception as e:
168
+ return f"Error converting document: {str(e)}"
169
+
170
+ def _convert_to_pdf(self, html_content: str, output_path: Path):
171
+ """Convert HTML to PDF using weasyprint."""
172
+ HTML(string=_normalize_unicode(html_content)).write_pdf(output_path)
173
+
174
+ def _convert_to_docx(self, html_content: str, output_path: Path):
175
+ """Convert HTML to DOCX using the internal converter."""
176
+ html_to_docx(html_content, output_path)
177
+
178
+ def _convert_to_markdown(self, html_content: str, output_path: Path):
179
+ """Convert HTML to Markdown."""
180
+ converter = html2text.HTML2Text()
181
+ converter.body_width = 0 # Don't wrap text
182
+ markdown = converter.handle(html_content)
183
+ output_path.write_text(markdown, encoding="utf-8")
184
+
185
+ def _convert_to_txt(self, html_content: str, output_path: Path):
186
+ """Convert HTML to plain text."""
187
+ soup = BeautifulSoup(html_content, "html.parser")
188
+ text = soup.get_text(separator="\n", strip=True)
189
+ output_path.write_text(text, encoding="utf-8")
190
+
191
+
192
+ if __name__ == "__main__":
193
+ print("=" * 70)
194
+ print("TEST: ConvertDocument Tool")
195
+ print("=" * 70)
196
+ print()
197
+
198
+ print("Setup: Creating test document...")
199
+ html_content = """<!DOCTYPE html>
200
+ <html>
201
+ <head>
202
+ <meta charset="UTF-8">
203
+ <title>Sample Report</title>
204
+ <style>
205
+ body { font-family: Arial, sans-serif; margin: 40px; }
206
+ h1 { color: #0066cc; }
207
+ h2 { color: #333; border-bottom: 2px solid #0066cc; padding-bottom: 5px; }
208
+ p { line-height: 1.6; }
209
+ table { border-collapse: collapse; width: 100%; margin: 20px 0; }
210
+ th { background: #0066cc; color: white; padding: 10px; text-align: left; }
211
+ td { border: 1px solid #ddd; padding: 8px; }
212
+ </style>
213
+ </head>
214
+ <body>
215
+ <h1>Annual Report 2026</h1>
216
+
217
+ <h2>Executive Summary</h2>
218
+ <p>
219
+ This report provides an overview of our company's performance in 2026.
220
+ We achieved significant growth across all key metrics.
221
+ </p>
222
+
223
+ <h2>Financial Highlights</h2>
224
+ <table>
225
+ <tr>
226
+ <th>Metric</th>
227
+ <th>2025</th>
228
+ <th>2026</th>
229
+ <th>Growth</th>
230
+ </tr>
231
+ <tr>
232
+ <td>Revenue</td>
233
+ <td>$10M</td>
234
+ <td>$15M</td>
235
+ <td>+50%</td>
236
+ </tr>
237
+ <tr>
238
+ <td>Customers</td>
239
+ <td>500</td>
240
+ <td>800</td>
241
+ <td>+60%</td>
242
+ </tr>
243
+ </table>
244
+
245
+ <h2>Key Achievements</h2>
246
+ <ul>
247
+ <li>Launched new product line</li>
248
+ <li>Expanded to 3 new markets</li>
249
+ <li>Achieved profitability</li>
250
+ </ul>
251
+ </body>
252
+ </html>"""
253
+
254
+ create_tool = CreateDocument(
255
+ project_name="test_convert",
256
+ document_name="annual_report",
257
+ content={"type": "html", "value": html_content},
258
+ overwrite=True,
259
+ )
260
+ print(create_tool.run())
261
+ print()
262
+
263
+ # Test 1: Convert to PDF
264
+ print("Test 1: Converting to PDF...")
265
+ tool = ConvertDocument(
266
+ project_name="test_convert",
267
+ document_name="annual_report",
268
+ output_format="pdf"
269
+ )
270
+ result = tool.run()
271
+ print(result)
272
+ print()
273
+
274
+ # Test 2: Convert to Markdown
275
+ print("Test 2: Converting to Markdown...")
276
+ tool = ConvertDocument(
277
+ project_name="test_convert",
278
+ document_name="annual_report",
279
+ output_format="markdown"
280
+ )
281
+ result = tool.run()
282
+ print(result)
283
+ print()
284
+
285
+ # Test 3: Convert to TXT
286
+ print("Test 3: Converting to plain text...")
287
+ tool = ConvertDocument(
288
+ project_name="test_convert",
289
+ document_name="annual_report",
290
+ output_format="txt"
291
+ )
292
+ result = tool.run()
293
+ print(result)
294
+ print()
295
+
296
+ # Test 4: View markdown output
297
+ if "✅" in result:
298
+ print("Test 4: Viewing converted Markdown content...")
299
+ from pathlib import Path
300
+ md_path = get_project_dir("test_convert") / "annual_report.md"
301
+ if md_path.exists():
302
+ print("Markdown content:")
303
+ print("-" * 70)
304
+ print(md_path.read_text(encoding='utf-8')[:500])
305
+ print("...")
306
+ print("-" * 70)
307
+ print()
308
+
309
+ # Test 5: Convert non-existent document (should fail)
310
+ print("Test 5: Attempting to convert non-existent document...")
311
+ tool = ConvertDocument(
312
+ project_name="test_convert",
313
+ document_name="nonexistent",
314
+ output_format="pdf"
315
+ )
316
+ print(tool.run())
317
+ print()
318
+
319
+ print("=" * 70)
320
+ print("✅ ALL TESTS COMPLETE")
321
+ print("=" * 70)
322
+ print("\nNote: Some conversion tests may show warnings if optional dependencies")
323
+ print("(weasyprint, html2text) are not installed. This is expected.")
@@ -0,0 +1,287 @@
1
+ """Create a new document from HTML or Markdown content."""
2
+
3
+ from pathlib import Path
4
+ from tempfile import TemporaryDirectory
5
+ from typing import Literal, Union
6
+
7
+ from agency_swarm.tools import BaseTool, ToolOutputText, tool_output_image_from_path
8
+ from playwright.sync_api import sync_playwright
9
+ from pydantic import BaseModel, Field
10
+ from .utils.html_validation import build_unsupported_error, find_unsupported_html
11
+ from .utils.html_docx_playwright import _launch_chromium_with_install
12
+ from .utils.html_docx_constants import _UA_RESET_STYLE
13
+ from .utils.doc_file_utils import get_project_dir
14
+ from .utils.html_docx_images import embed_local_images
15
+
16
+
17
+ class HtmlContent(BaseModel):
18
+ type: Literal["html"]
19
+ value: str
20
+
21
+
22
+ class MarkdownContent(BaseModel):
23
+ type: Literal["markdown"]
24
+ value: str
25
+
26
+
27
+ ContentInput = Union[HtmlContent, MarkdownContent]
28
+
29
+
30
+ class CreateDocument(BaseTool):
31
+ """
32
+ Create a new document from HTML or Markdown content.
33
+
34
+ HTML workflow creates:
35
+ - .source.html file (the canonical source of truth)
36
+
37
+ Markdown workflow creates:
38
+ - .md file only (no .docx or .pdf generation)
39
+
40
+ HTML is used as the source format because it provides:
41
+ - Full styling control (fonts, colors, spacing, etc.)
42
+ - Standard conversion tools (weasyprint)
43
+ - WYSIWYG editing experience
44
+ - Easy web preview capability
45
+
46
+ Use this tool to create new documents with custom formatting and styling.
47
+ """
48
+
49
+ project_name: str = Field(
50
+ ...,
51
+ description="Name of the project folder (creates/uses ./mnt/{project_name}/documents/). Use lowercase with underscores (e.g., 'business_proposals', 'client_reports')"
52
+ )
53
+
54
+ document_name: str = Field(
55
+ ...,
56
+ description="Name of the document file without extension (e.g., 'quarterly_report', 'contract_template'). Extension will be added automatically."
57
+ )
58
+
59
+ content: ContentInput = Field(
60
+ ...,
61
+ description="""Content object for the document.
62
+
63
+ HTML example:
64
+ {
65
+ "type": "html",
66
+ "value": "<!DOCTYPE html>..."
67
+ }
68
+
69
+ Markdown example:
70
+ {
71
+ "type": "markdown",
72
+ "value": "# Title\\n\\n- Item"
73
+ }
74
+ """
75
+ )
76
+
77
+ overwrite: bool = Field(
78
+ default=False,
79
+ description="If True, overwrites existing document. If False (default), returns an error if document already exists."
80
+ )
81
+
82
+ def run(self):
83
+ """Create a new document from HTML or Markdown content."""
84
+ try:
85
+ project_dir = get_project_dir(self.project_name)
86
+ project_dir.mkdir(parents=True, exist_ok=True)
87
+ (project_dir / "assets").mkdir(exist_ok=True)
88
+
89
+ # Strip extension if the caller included one
90
+ doc_name = (
91
+ self.document_name.replace(".html", "")
92
+ .replace(".docx", "")
93
+ .replace(".md", "")
94
+ )
95
+
96
+ content_value = self.content.value
97
+ if not content_value:
98
+ return "Error: content.value is required."
99
+
100
+ if self.content.type == "markdown":
101
+ return self._create_markdown(doc_name, project_dir, content_value)
102
+
103
+ source_path = project_dir / f"{doc_name}.source.html"
104
+
105
+ if source_path.exists() and not self.overwrite:
106
+ return f"Error: Document '{doc_name}' already exists in project '{self.project_name}'. Use overwrite=True to replace it, or choose a different document name."
107
+
108
+ normalized_html = _ensure_ua_reset(content_value)
109
+ issues = find_unsupported_html(normalized_html)
110
+ if issues:
111
+ return build_unsupported_error(issues)
112
+ source_path.write_text(normalized_html, encoding='utf-8')
113
+
114
+ source_size = source_path.stat().st_size
115
+
116
+ operation = "updated" if self.overwrite and source_path.exists() else "created"
117
+
118
+ message = f"""Successfully {operation} document
119
+
120
+ Project: {self.project_name}
121
+ Document: {doc_name}
122
+
123
+ Files created:
124
+ - {source_path.name} ({source_size:,} bytes)
125
+
126
+ Path: {source_path}
127
+
128
+ Note: The .source.html file is the canonical source to be used for document conversion."""
129
+ try:
130
+ preview = _build_html_preview_image(normalized_html, project_dir)
131
+ except Exception:
132
+ return ToolOutputText(text=message)
133
+
134
+ return [
135
+ ToolOutputText(text=message),
136
+ preview,
137
+ ]
138
+
139
+ except Exception as e:
140
+ return f"Error creating document: {str(e)}"
141
+
142
+ def _create_markdown(self, doc_name, project_dir, markdown_value):
143
+ md_path = project_dir / f"{doc_name}.md"
144
+ if md_path.exists() and not self.overwrite:
145
+ return f"Error: Document '{doc_name}' already exists in project '{self.project_name}'. Use overwrite=True to replace it, or choose a different document name."
146
+
147
+ md_path.write_text(markdown_value, encoding="utf-8")
148
+ if not md_path.exists():
149
+ return f"Error: Markdown generation failed for document '{doc_name}'."
150
+ md_size = md_path.stat().st_size
151
+ operation = "updated" if self.overwrite and md_path.exists() else "created"
152
+
153
+ return f"""Successfully {operation} document!
154
+
155
+ Project: {self.project_name}
156
+ Document: {doc_name}
157
+
158
+ Files created:
159
+ - {md_path.name} ({md_size:,} bytes) [Markdown source]
160
+
161
+ Path: {md_path}
162
+
163
+ Note: Markdown workflow only creates a .md file and does not generate .docx or .pdf files."""
164
+
165
+ def _build_html_preview_image(html_content: str, base_dir: Path):
166
+ """Render a preview JPEG of the HTML document.
167
+
168
+ The temp file is written inside base_dir so Playwright resolves
169
+ relative image paths correctly (mirrors the slides-agent pattern).
170
+ Images are also embedded as data URIs for full fidelity.
171
+ """
172
+ import tempfile
173
+
174
+ from PIL import Image
175
+
176
+ preview_html = embed_local_images(html_content, base_dir)
177
+
178
+ with tempfile.NamedTemporaryFile(
179
+ mode="w",
180
+ suffix=".html",
181
+ delete=False,
182
+ encoding="utf-8",
183
+ dir=base_dir,
184
+ ) as tmp_html:
185
+ tmp_html.write(preview_html)
186
+ tmp_html_path = Path(tmp_html.name)
187
+
188
+ try:
189
+ with TemporaryDirectory() as tmp_dir:
190
+ tmp_dir_path = Path(tmp_dir)
191
+ raw_jpg = tmp_dir_path / "preview_raw.jpg"
192
+ out_jpg = tmp_dir_path / "preview.jpg"
193
+
194
+ with sync_playwright() as p:
195
+ browser = _launch_chromium_with_install(p)
196
+ page = browser.new_page(viewport={"width": 794, "height": 1123})
197
+ page.goto(tmp_html_path.as_uri())
198
+ page.wait_for_load_state("networkidle")
199
+ page.screenshot(path=str(raw_jpg), full_page=True, type="jpeg", quality=80)
200
+ browser.close()
201
+
202
+ img = Image.open(raw_jpg)
203
+ new_size = (int(img.width * 0.75), int(img.height * 0.75))
204
+ img = img.resize(new_size, Image.Resampling.LANCZOS)
205
+ img.save(out_jpg, "JPEG", quality=75, optimize=True)
206
+
207
+ return tool_output_image_from_path(out_jpg, detail="auto")
208
+ finally:
209
+ tmp_html_path.unlink(missing_ok=True)
210
+
211
+ def _ensure_ua_reset(html_content: str) -> str:
212
+ """Ensure a UA reset style exists in the HTML head."""
213
+ if "UA reset to neutralize browser defaults" in html_content:
214
+ return html_content
215
+
216
+ lower = html_content.lower()
217
+ head_index = lower.find("<head")
218
+ if head_index != -1:
219
+ head_close = lower.find(">", head_index)
220
+ if head_close != -1:
221
+ return (
222
+ html_content[: head_close + 1]
223
+ + _UA_RESET_STYLE
224
+ + html_content[head_close + 1 :]
225
+ )
226
+
227
+ if "<html" in lower:
228
+ return html_content.replace("<html>", f"<html><head>{_UA_RESET_STYLE}</head>", 1)
229
+
230
+ return f"<!DOCTYPE html><html><head>{_UA_RESET_STYLE}</head><body>{html_content}</body></html>"
231
+
232
+ if __name__ == "__main__":
233
+ print("=" * 70)
234
+ print("TEST: CreateDocument Tool")
235
+ print("=" * 70)
236
+ print()
237
+ html_simple = """<!DOCTYPE html>
238
+ <html>
239
+ <head>
240
+ <meta charset="UTF-8">
241
+ <title>Business Proposal</title>
242
+ </head>
243
+ <body>
244
+ <h1 style="color: #0066cc; font-family: Arial, sans-serif;">Business Proposal</h1>
245
+
246
+ <h2 style="color: #333; font-family: Arial, sans-serif;">Executive Summary</h2>
247
+ <p style="font-family: Georgia, serif; font-size: 11pt; line-height: 1.5;">
248
+ This proposal outlines our comprehensive approach to solving your business challenges.
249
+ We bring extensive experience and proven methodologies to deliver results.
250
+ </p>
251
+
252
+ <h2 style="color: #333; font-family: Arial, sans-serif;">Our Services</h2>
253
+ <ul style="font-family: Georgia, serif; font-size: 11pt; line-height: 1.5;">
254
+ <li><strong>Consulting:</strong> Strategic business advisory</li>
255
+ <li><strong>Implementation:</strong> End-to-end project execution</li>
256
+ <li><strong>Support:</strong> Ongoing maintenance and optimization</li>
257
+ </ul>
258
+
259
+ <h2 style="color: #333; font-family: Arial, sans-serif;">Pricing</h2>
260
+ <table style="width: 100%; border-collapse: collapse; font-family: Arial, sans-serif; font-size: 10pt;">
261
+ <tr style="background: #0066cc; color: white;">
262
+ <th style="padding: 10px; border: 1px solid #ccc; text-align: left;">Package</th>
263
+ <th style="padding: 10px; border: 1px solid #ccc; text-align: right;">Price</th>
264
+ </tr>
265
+ <tr>
266
+ <td style="padding: 8px; border: 1px solid #ccc;">Basic</td>
267
+ <td style="padding: 8px; border: 1px solid #ccc; text-align: right;">$5,000</td>
268
+ </tr>
269
+ <tr style="background: #f9f9f9;">
270
+ <td style="padding: 8px; border: 1px solid #ccc;">Professional</td>
271
+ <td style="padding: 8px; border: 1px solid #ccc; text-align: right;">$10,000</td>
272
+ </tr>
273
+ <tr>
274
+ <td style="padding: 8px; border: 1px solid #ccc;">Enterprise</td>
275
+ <td style="padding: 8px; border: 1px solid #ccc; text-align: right;">$25,000</td>
276
+ </tr>
277
+ </table>
278
+ </body>
279
+ </html>"""
280
+
281
+ tool = CreateDocument(
282
+ project_name="test_project",
283
+ document_name="business_proposal",
284
+ content={"type": "html", "value": html_simple},
285
+ )
286
+ print(tool.run())
287
+ print()