ai-parrot 0.17.2__cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

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 (535) hide show
  1. agentui/.prettierrc +15 -0
  2. agentui/QUICKSTART.md +272 -0
  3. agentui/README.md +59 -0
  4. agentui/env.example +16 -0
  5. agentui/jsconfig.json +14 -0
  6. agentui/package-lock.json +4242 -0
  7. agentui/package.json +34 -0
  8. agentui/scripts/postinstall/apply-patches.mjs +260 -0
  9. agentui/src/app.css +61 -0
  10. agentui/src/app.d.ts +13 -0
  11. agentui/src/app.html +12 -0
  12. agentui/src/components/LoadingSpinner.svelte +64 -0
  13. agentui/src/components/ThemeSwitcher.svelte +159 -0
  14. agentui/src/components/index.js +4 -0
  15. agentui/src/lib/api/bots.ts +60 -0
  16. agentui/src/lib/api/chat.ts +22 -0
  17. agentui/src/lib/api/http.ts +25 -0
  18. agentui/src/lib/components/BotCard.svelte +33 -0
  19. agentui/src/lib/components/ChatBubble.svelte +63 -0
  20. agentui/src/lib/components/Toast.svelte +21 -0
  21. agentui/src/lib/config.ts +20 -0
  22. agentui/src/lib/stores/auth.svelte.ts +73 -0
  23. agentui/src/lib/stores/theme.svelte.js +64 -0
  24. agentui/src/lib/stores/toast.svelte.ts +31 -0
  25. agentui/src/lib/utils/conversation.ts +39 -0
  26. agentui/src/routes/+layout.svelte +20 -0
  27. agentui/src/routes/+page.svelte +232 -0
  28. agentui/src/routes/login/+page.svelte +200 -0
  29. agentui/src/routes/talk/[agentId]/+page.svelte +297 -0
  30. agentui/src/routes/talk/[agentId]/+page.ts +7 -0
  31. agentui/static/README.md +1 -0
  32. agentui/svelte.config.js +11 -0
  33. agentui/tailwind.config.ts +53 -0
  34. agentui/tsconfig.json +3 -0
  35. agentui/vite.config.ts +10 -0
  36. ai_parrot-0.17.2.dist-info/METADATA +472 -0
  37. ai_parrot-0.17.2.dist-info/RECORD +535 -0
  38. ai_parrot-0.17.2.dist-info/WHEEL +6 -0
  39. ai_parrot-0.17.2.dist-info/entry_points.txt +2 -0
  40. ai_parrot-0.17.2.dist-info/licenses/LICENSE +21 -0
  41. ai_parrot-0.17.2.dist-info/top_level.txt +6 -0
  42. crew-builder/.prettierrc +15 -0
  43. crew-builder/QUICKSTART.md +259 -0
  44. crew-builder/README.md +113 -0
  45. crew-builder/env.example +17 -0
  46. crew-builder/jsconfig.json +14 -0
  47. crew-builder/package-lock.json +4182 -0
  48. crew-builder/package.json +37 -0
  49. crew-builder/scripts/postinstall/apply-patches.mjs +260 -0
  50. crew-builder/src/app.css +62 -0
  51. crew-builder/src/app.d.ts +13 -0
  52. crew-builder/src/app.html +12 -0
  53. crew-builder/src/components/LoadingSpinner.svelte +64 -0
  54. crew-builder/src/components/ThemeSwitcher.svelte +149 -0
  55. crew-builder/src/components/index.js +9 -0
  56. crew-builder/src/lib/api/bots.ts +60 -0
  57. crew-builder/src/lib/api/chat.ts +80 -0
  58. crew-builder/src/lib/api/client.ts +56 -0
  59. crew-builder/src/lib/api/crew/crew.ts +136 -0
  60. crew-builder/src/lib/api/index.ts +5 -0
  61. crew-builder/src/lib/api/o365/auth.ts +65 -0
  62. crew-builder/src/lib/auth/auth.ts +54 -0
  63. crew-builder/src/lib/components/AgentNode.svelte +43 -0
  64. crew-builder/src/lib/components/BotCard.svelte +33 -0
  65. crew-builder/src/lib/components/ChatBubble.svelte +67 -0
  66. crew-builder/src/lib/components/ConfigPanel.svelte +278 -0
  67. crew-builder/src/lib/components/JsonTreeNode.svelte +76 -0
  68. crew-builder/src/lib/components/JsonViewer.svelte +24 -0
  69. crew-builder/src/lib/components/MarkdownEditor.svelte +48 -0
  70. crew-builder/src/lib/components/ThemeToggle.svelte +36 -0
  71. crew-builder/src/lib/components/Toast.svelte +67 -0
  72. crew-builder/src/lib/components/Toolbar.svelte +157 -0
  73. crew-builder/src/lib/components/index.ts +10 -0
  74. crew-builder/src/lib/config.ts +8 -0
  75. crew-builder/src/lib/stores/auth.svelte.ts +228 -0
  76. crew-builder/src/lib/stores/crewStore.ts +369 -0
  77. crew-builder/src/lib/stores/theme.svelte.js +145 -0
  78. crew-builder/src/lib/stores/toast.svelte.ts +69 -0
  79. crew-builder/src/lib/utils/conversation.ts +39 -0
  80. crew-builder/src/lib/utils/markdown.ts +122 -0
  81. crew-builder/src/lib/utils/talkHistory.ts +47 -0
  82. crew-builder/src/routes/+layout.svelte +20 -0
  83. crew-builder/src/routes/+page.svelte +539 -0
  84. crew-builder/src/routes/agents/+page.svelte +247 -0
  85. crew-builder/src/routes/agents/[agentId]/+page.svelte +288 -0
  86. crew-builder/src/routes/agents/[agentId]/+page.ts +7 -0
  87. crew-builder/src/routes/builder/+page.svelte +204 -0
  88. crew-builder/src/routes/crew/ask/+page.svelte +1052 -0
  89. crew-builder/src/routes/crew/ask/+page.ts +1 -0
  90. crew-builder/src/routes/integrations/o365/+page.svelte +304 -0
  91. crew-builder/src/routes/login/+page.svelte +197 -0
  92. crew-builder/src/routes/talk/[agentId]/+page.svelte +487 -0
  93. crew-builder/src/routes/talk/[agentId]/+page.ts +7 -0
  94. crew-builder/static/README.md +1 -0
  95. crew-builder/svelte.config.js +11 -0
  96. crew-builder/tailwind.config.ts +53 -0
  97. crew-builder/tsconfig.json +3 -0
  98. crew-builder/vite.config.ts +10 -0
  99. mcp_servers/calculator_server.py +309 -0
  100. parrot/__init__.py +27 -0
  101. parrot/__pycache__/__init__.cpython-310.pyc +0 -0
  102. parrot/__pycache__/version.cpython-310.pyc +0 -0
  103. parrot/_version.py +34 -0
  104. parrot/a2a/__init__.py +48 -0
  105. parrot/a2a/client.py +658 -0
  106. parrot/a2a/discovery.py +89 -0
  107. parrot/a2a/mixin.py +257 -0
  108. parrot/a2a/models.py +376 -0
  109. parrot/a2a/server.py +770 -0
  110. parrot/agents/__init__.py +29 -0
  111. parrot/bots/__init__.py +12 -0
  112. parrot/bots/a2a_agent.py +19 -0
  113. parrot/bots/abstract.py +3139 -0
  114. parrot/bots/agent.py +1129 -0
  115. parrot/bots/basic.py +9 -0
  116. parrot/bots/chatbot.py +669 -0
  117. parrot/bots/data.py +1618 -0
  118. parrot/bots/database/__init__.py +5 -0
  119. parrot/bots/database/abstract.py +3071 -0
  120. parrot/bots/database/cache.py +286 -0
  121. parrot/bots/database/models.py +468 -0
  122. parrot/bots/database/prompts.py +154 -0
  123. parrot/bots/database/retries.py +98 -0
  124. parrot/bots/database/router.py +269 -0
  125. parrot/bots/database/sql.py +41 -0
  126. parrot/bots/db/__init__.py +6 -0
  127. parrot/bots/db/abstract.py +556 -0
  128. parrot/bots/db/bigquery.py +602 -0
  129. parrot/bots/db/cache.py +85 -0
  130. parrot/bots/db/documentdb.py +668 -0
  131. parrot/bots/db/elastic.py +1014 -0
  132. parrot/bots/db/influx.py +898 -0
  133. parrot/bots/db/mock.py +96 -0
  134. parrot/bots/db/multi.py +783 -0
  135. parrot/bots/db/prompts.py +185 -0
  136. parrot/bots/db/sql.py +1255 -0
  137. parrot/bots/db/tools.py +212 -0
  138. parrot/bots/document.py +680 -0
  139. parrot/bots/hrbot.py +15 -0
  140. parrot/bots/kb.py +170 -0
  141. parrot/bots/mcp.py +36 -0
  142. parrot/bots/orchestration/README.md +463 -0
  143. parrot/bots/orchestration/__init__.py +1 -0
  144. parrot/bots/orchestration/agent.py +155 -0
  145. parrot/bots/orchestration/crew.py +3330 -0
  146. parrot/bots/orchestration/fsm.py +1179 -0
  147. parrot/bots/orchestration/hr.py +434 -0
  148. parrot/bots/orchestration/storage/__init__.py +4 -0
  149. parrot/bots/orchestration/storage/memory.py +100 -0
  150. parrot/bots/orchestration/storage/mixin.py +119 -0
  151. parrot/bots/orchestration/verify.py +202 -0
  152. parrot/bots/product.py +204 -0
  153. parrot/bots/prompts/__init__.py +96 -0
  154. parrot/bots/prompts/agents.py +155 -0
  155. parrot/bots/prompts/data.py +216 -0
  156. parrot/bots/prompts/output_generation.py +8 -0
  157. parrot/bots/scraper/__init__.py +3 -0
  158. parrot/bots/scraper/models.py +122 -0
  159. parrot/bots/scraper/scraper.py +1173 -0
  160. parrot/bots/scraper/templates.py +115 -0
  161. parrot/bots/stores/__init__.py +5 -0
  162. parrot/bots/stores/local.py +172 -0
  163. parrot/bots/webdev.py +81 -0
  164. parrot/cli.py +17 -0
  165. parrot/clients/__init__.py +16 -0
  166. parrot/clients/base.py +1491 -0
  167. parrot/clients/claude.py +1191 -0
  168. parrot/clients/factory.py +129 -0
  169. parrot/clients/google.py +4567 -0
  170. parrot/clients/gpt.py +1975 -0
  171. parrot/clients/grok.py +432 -0
  172. parrot/clients/groq.py +986 -0
  173. parrot/clients/hf.py +582 -0
  174. parrot/clients/models.py +18 -0
  175. parrot/conf.py +395 -0
  176. parrot/embeddings/__init__.py +9 -0
  177. parrot/embeddings/base.py +157 -0
  178. parrot/embeddings/google.py +98 -0
  179. parrot/embeddings/huggingface.py +74 -0
  180. parrot/embeddings/openai.py +84 -0
  181. parrot/embeddings/processor.py +88 -0
  182. parrot/exceptions.c +13868 -0
  183. parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
  184. parrot/exceptions.pxd +22 -0
  185. parrot/exceptions.pxi +15 -0
  186. parrot/exceptions.pyx +44 -0
  187. parrot/generators/__init__.py +29 -0
  188. parrot/generators/base.py +200 -0
  189. parrot/generators/html.py +293 -0
  190. parrot/generators/react.py +205 -0
  191. parrot/generators/streamlit.py +203 -0
  192. parrot/generators/template.py +105 -0
  193. parrot/handlers/__init__.py +4 -0
  194. parrot/handlers/agent.py +861 -0
  195. parrot/handlers/agents/__init__.py +1 -0
  196. parrot/handlers/agents/abstract.py +900 -0
  197. parrot/handlers/bots.py +338 -0
  198. parrot/handlers/chat.py +915 -0
  199. parrot/handlers/creation.sql +192 -0
  200. parrot/handlers/crew/ARCHITECTURE.md +362 -0
  201. parrot/handlers/crew/README_BOTMANAGER_PERSISTENCE.md +303 -0
  202. parrot/handlers/crew/README_REDIS_PERSISTENCE.md +366 -0
  203. parrot/handlers/crew/__init__.py +0 -0
  204. parrot/handlers/crew/handler.py +801 -0
  205. parrot/handlers/crew/models.py +229 -0
  206. parrot/handlers/crew/redis_persistence.py +523 -0
  207. parrot/handlers/jobs/__init__.py +10 -0
  208. parrot/handlers/jobs/job.py +384 -0
  209. parrot/handlers/jobs/mixin.py +627 -0
  210. parrot/handlers/jobs/models.py +115 -0
  211. parrot/handlers/jobs/worker.py +31 -0
  212. parrot/handlers/models.py +596 -0
  213. parrot/handlers/o365_auth.py +105 -0
  214. parrot/handlers/stream.py +337 -0
  215. parrot/interfaces/__init__.py +6 -0
  216. parrot/interfaces/aws.py +143 -0
  217. parrot/interfaces/credentials.py +113 -0
  218. parrot/interfaces/database.py +27 -0
  219. parrot/interfaces/google.py +1123 -0
  220. parrot/interfaces/hierarchy.py +1227 -0
  221. parrot/interfaces/http.py +651 -0
  222. parrot/interfaces/images/__init__.py +0 -0
  223. parrot/interfaces/images/plugins/__init__.py +24 -0
  224. parrot/interfaces/images/plugins/abstract.py +58 -0
  225. parrot/interfaces/images/plugins/analisys.py +148 -0
  226. parrot/interfaces/images/plugins/classify.py +150 -0
  227. parrot/interfaces/images/plugins/classifybase.py +182 -0
  228. parrot/interfaces/images/plugins/detect.py +150 -0
  229. parrot/interfaces/images/plugins/exif.py +1103 -0
  230. parrot/interfaces/images/plugins/hash.py +52 -0
  231. parrot/interfaces/images/plugins/vision.py +104 -0
  232. parrot/interfaces/images/plugins/yolo.py +66 -0
  233. parrot/interfaces/images/plugins/zerodetect.py +197 -0
  234. parrot/interfaces/o365.py +978 -0
  235. parrot/interfaces/onedrive.py +822 -0
  236. parrot/interfaces/sharepoint.py +1435 -0
  237. parrot/interfaces/soap.py +257 -0
  238. parrot/loaders/__init__.py +8 -0
  239. parrot/loaders/abstract.py +1131 -0
  240. parrot/loaders/audio.py +199 -0
  241. parrot/loaders/basepdf.py +53 -0
  242. parrot/loaders/basevideo.py +1568 -0
  243. parrot/loaders/csv.py +409 -0
  244. parrot/loaders/docx.py +116 -0
  245. parrot/loaders/epubloader.py +316 -0
  246. parrot/loaders/excel.py +199 -0
  247. parrot/loaders/factory.py +55 -0
  248. parrot/loaders/files/__init__.py +0 -0
  249. parrot/loaders/files/abstract.py +39 -0
  250. parrot/loaders/files/html.py +26 -0
  251. parrot/loaders/files/text.py +63 -0
  252. parrot/loaders/html.py +152 -0
  253. parrot/loaders/markdown.py +442 -0
  254. parrot/loaders/pdf.py +373 -0
  255. parrot/loaders/pdfmark.py +320 -0
  256. parrot/loaders/pdftables.py +506 -0
  257. parrot/loaders/ppt.py +476 -0
  258. parrot/loaders/qa.py +63 -0
  259. parrot/loaders/splitters/__init__.py +10 -0
  260. parrot/loaders/splitters/base.py +138 -0
  261. parrot/loaders/splitters/md.py +228 -0
  262. parrot/loaders/splitters/token.py +143 -0
  263. parrot/loaders/txt.py +26 -0
  264. parrot/loaders/video.py +89 -0
  265. parrot/loaders/videolocal.py +218 -0
  266. parrot/loaders/videounderstanding.py +377 -0
  267. parrot/loaders/vimeo.py +167 -0
  268. parrot/loaders/web.py +599 -0
  269. parrot/loaders/youtube.py +504 -0
  270. parrot/manager/__init__.py +5 -0
  271. parrot/manager/manager.py +1030 -0
  272. parrot/mcp/__init__.py +28 -0
  273. parrot/mcp/adapter.py +105 -0
  274. parrot/mcp/cli.py +174 -0
  275. parrot/mcp/client.py +119 -0
  276. parrot/mcp/config.py +75 -0
  277. parrot/mcp/integration.py +842 -0
  278. parrot/mcp/oauth.py +933 -0
  279. parrot/mcp/server.py +225 -0
  280. parrot/mcp/transports/__init__.py +3 -0
  281. parrot/mcp/transports/base.py +279 -0
  282. parrot/mcp/transports/grpc_session.py +163 -0
  283. parrot/mcp/transports/http.py +312 -0
  284. parrot/mcp/transports/mcp.proto +108 -0
  285. parrot/mcp/transports/quic.py +1082 -0
  286. parrot/mcp/transports/sse.py +330 -0
  287. parrot/mcp/transports/stdio.py +309 -0
  288. parrot/mcp/transports/unix.py +395 -0
  289. parrot/mcp/transports/websocket.py +547 -0
  290. parrot/memory/__init__.py +16 -0
  291. parrot/memory/abstract.py +209 -0
  292. parrot/memory/agent.py +32 -0
  293. parrot/memory/cache.py +175 -0
  294. parrot/memory/core.py +555 -0
  295. parrot/memory/file.py +153 -0
  296. parrot/memory/mem.py +131 -0
  297. parrot/memory/redis.py +613 -0
  298. parrot/models/__init__.py +46 -0
  299. parrot/models/basic.py +118 -0
  300. parrot/models/compliance.py +208 -0
  301. parrot/models/crew.py +395 -0
  302. parrot/models/detections.py +654 -0
  303. parrot/models/generation.py +85 -0
  304. parrot/models/google.py +223 -0
  305. parrot/models/groq.py +23 -0
  306. parrot/models/openai.py +30 -0
  307. parrot/models/outputs.py +285 -0
  308. parrot/models/responses.py +938 -0
  309. parrot/notifications/__init__.py +743 -0
  310. parrot/openapi/__init__.py +3 -0
  311. parrot/openapi/components.yaml +641 -0
  312. parrot/openapi/config.py +322 -0
  313. parrot/outputs/__init__.py +32 -0
  314. parrot/outputs/formats/__init__.py +108 -0
  315. parrot/outputs/formats/altair.py +359 -0
  316. parrot/outputs/formats/application.py +122 -0
  317. parrot/outputs/formats/base.py +351 -0
  318. parrot/outputs/formats/bokeh.py +356 -0
  319. parrot/outputs/formats/card.py +424 -0
  320. parrot/outputs/formats/chart.py +436 -0
  321. parrot/outputs/formats/d3.py +255 -0
  322. parrot/outputs/formats/echarts.py +310 -0
  323. parrot/outputs/formats/generators/__init__.py +0 -0
  324. parrot/outputs/formats/generators/abstract.py +61 -0
  325. parrot/outputs/formats/generators/panel.py +145 -0
  326. parrot/outputs/formats/generators/streamlit.py +86 -0
  327. parrot/outputs/formats/generators/terminal.py +63 -0
  328. parrot/outputs/formats/holoviews.py +310 -0
  329. parrot/outputs/formats/html.py +147 -0
  330. parrot/outputs/formats/jinja2.py +46 -0
  331. parrot/outputs/formats/json.py +87 -0
  332. parrot/outputs/formats/map.py +933 -0
  333. parrot/outputs/formats/markdown.py +172 -0
  334. parrot/outputs/formats/matplotlib.py +237 -0
  335. parrot/outputs/formats/mixins/__init__.py +0 -0
  336. parrot/outputs/formats/mixins/emaps.py +855 -0
  337. parrot/outputs/formats/plotly.py +341 -0
  338. parrot/outputs/formats/seaborn.py +310 -0
  339. parrot/outputs/formats/table.py +397 -0
  340. parrot/outputs/formats/template_report.py +138 -0
  341. parrot/outputs/formats/yaml.py +125 -0
  342. parrot/outputs/formatter.py +152 -0
  343. parrot/outputs/templates/__init__.py +95 -0
  344. parrot/pipelines/__init__.py +0 -0
  345. parrot/pipelines/abstract.py +210 -0
  346. parrot/pipelines/detector.py +124 -0
  347. parrot/pipelines/models.py +90 -0
  348. parrot/pipelines/planogram.py +3002 -0
  349. parrot/pipelines/table.sql +97 -0
  350. parrot/plugins/__init__.py +106 -0
  351. parrot/plugins/importer.py +80 -0
  352. parrot/py.typed +0 -0
  353. parrot/registry/__init__.py +18 -0
  354. parrot/registry/registry.py +594 -0
  355. parrot/scheduler/__init__.py +1189 -0
  356. parrot/scheduler/models.py +60 -0
  357. parrot/security/__init__.py +16 -0
  358. parrot/security/prompt_injection.py +268 -0
  359. parrot/security/security_events.sql +25 -0
  360. parrot/services/__init__.py +1 -0
  361. parrot/services/mcp/__init__.py +8 -0
  362. parrot/services/mcp/config.py +13 -0
  363. parrot/services/mcp/server.py +295 -0
  364. parrot/services/o365_remote_auth.py +235 -0
  365. parrot/stores/__init__.py +7 -0
  366. parrot/stores/abstract.py +352 -0
  367. parrot/stores/arango.py +1090 -0
  368. parrot/stores/bigquery.py +1377 -0
  369. parrot/stores/cache.py +106 -0
  370. parrot/stores/empty.py +10 -0
  371. parrot/stores/faiss_store.py +1157 -0
  372. parrot/stores/kb/__init__.py +9 -0
  373. parrot/stores/kb/abstract.py +68 -0
  374. parrot/stores/kb/cache.py +165 -0
  375. parrot/stores/kb/doc.py +325 -0
  376. parrot/stores/kb/hierarchy.py +346 -0
  377. parrot/stores/kb/local.py +457 -0
  378. parrot/stores/kb/prompt.py +28 -0
  379. parrot/stores/kb/redis.py +659 -0
  380. parrot/stores/kb/store.py +115 -0
  381. parrot/stores/kb/user.py +374 -0
  382. parrot/stores/models.py +59 -0
  383. parrot/stores/pgvector.py +3 -0
  384. parrot/stores/postgres.py +2853 -0
  385. parrot/stores/utils/__init__.py +0 -0
  386. parrot/stores/utils/chunking.py +197 -0
  387. parrot/telemetry/__init__.py +3 -0
  388. parrot/telemetry/mixin.py +111 -0
  389. parrot/template/__init__.py +3 -0
  390. parrot/template/engine.py +259 -0
  391. parrot/tools/__init__.py +23 -0
  392. parrot/tools/abstract.py +644 -0
  393. parrot/tools/agent.py +363 -0
  394. parrot/tools/arangodbsearch.py +537 -0
  395. parrot/tools/arxiv_tool.py +188 -0
  396. parrot/tools/calculator/__init__.py +3 -0
  397. parrot/tools/calculator/operations/__init__.py +38 -0
  398. parrot/tools/calculator/operations/calculus.py +80 -0
  399. parrot/tools/calculator/operations/statistics.py +76 -0
  400. parrot/tools/calculator/tool.py +150 -0
  401. parrot/tools/cloudwatch.py +988 -0
  402. parrot/tools/codeinterpreter/__init__.py +127 -0
  403. parrot/tools/codeinterpreter/executor.py +371 -0
  404. parrot/tools/codeinterpreter/internals.py +473 -0
  405. parrot/tools/codeinterpreter/models.py +643 -0
  406. parrot/tools/codeinterpreter/prompts.py +224 -0
  407. parrot/tools/codeinterpreter/tool.py +664 -0
  408. parrot/tools/company_info/__init__.py +6 -0
  409. parrot/tools/company_info/tool.py +1138 -0
  410. parrot/tools/correlationanalysis.py +437 -0
  411. parrot/tools/database/abstract.py +286 -0
  412. parrot/tools/database/bq.py +115 -0
  413. parrot/tools/database/cache.py +284 -0
  414. parrot/tools/database/models.py +95 -0
  415. parrot/tools/database/pg.py +343 -0
  416. parrot/tools/databasequery.py +1159 -0
  417. parrot/tools/db.py +1800 -0
  418. parrot/tools/ddgo.py +370 -0
  419. parrot/tools/decorators.py +271 -0
  420. parrot/tools/dftohtml.py +282 -0
  421. parrot/tools/document.py +549 -0
  422. parrot/tools/ecs.py +819 -0
  423. parrot/tools/edareport.py +368 -0
  424. parrot/tools/elasticsearch.py +1049 -0
  425. parrot/tools/employees.py +462 -0
  426. parrot/tools/epson/__init__.py +96 -0
  427. parrot/tools/excel.py +683 -0
  428. parrot/tools/file/__init__.py +13 -0
  429. parrot/tools/file/abstract.py +76 -0
  430. parrot/tools/file/gcs.py +378 -0
  431. parrot/tools/file/local.py +284 -0
  432. parrot/tools/file/s3.py +511 -0
  433. parrot/tools/file/tmp.py +309 -0
  434. parrot/tools/file/tool.py +501 -0
  435. parrot/tools/file_reader.py +129 -0
  436. parrot/tools/flowtask/__init__.py +19 -0
  437. parrot/tools/flowtask/tool.py +761 -0
  438. parrot/tools/gittoolkit.py +508 -0
  439. parrot/tools/google/__init__.py +18 -0
  440. parrot/tools/google/base.py +169 -0
  441. parrot/tools/google/tools.py +1251 -0
  442. parrot/tools/googlelocation.py +5 -0
  443. parrot/tools/googleroutes.py +5 -0
  444. parrot/tools/googlesearch.py +5 -0
  445. parrot/tools/googlesitesearch.py +5 -0
  446. parrot/tools/googlevoice.py +2 -0
  447. parrot/tools/gvoice.py +695 -0
  448. parrot/tools/ibisworld/README.md +225 -0
  449. parrot/tools/ibisworld/__init__.py +11 -0
  450. parrot/tools/ibisworld/tool.py +366 -0
  451. parrot/tools/jiratoolkit.py +1718 -0
  452. parrot/tools/manager.py +1098 -0
  453. parrot/tools/math.py +152 -0
  454. parrot/tools/metadata.py +476 -0
  455. parrot/tools/msteams.py +1621 -0
  456. parrot/tools/msword.py +635 -0
  457. parrot/tools/multidb.py +580 -0
  458. parrot/tools/multistoresearch.py +369 -0
  459. parrot/tools/networkninja.py +167 -0
  460. parrot/tools/nextstop/__init__.py +4 -0
  461. parrot/tools/nextstop/base.py +286 -0
  462. parrot/tools/nextstop/employee.py +733 -0
  463. parrot/tools/nextstop/store.py +462 -0
  464. parrot/tools/notification.py +435 -0
  465. parrot/tools/o365/__init__.py +42 -0
  466. parrot/tools/o365/base.py +295 -0
  467. parrot/tools/o365/bundle.py +522 -0
  468. parrot/tools/o365/events.py +554 -0
  469. parrot/tools/o365/mail.py +992 -0
  470. parrot/tools/o365/onedrive.py +497 -0
  471. parrot/tools/o365/sharepoint.py +641 -0
  472. parrot/tools/openapi_toolkit.py +904 -0
  473. parrot/tools/openweather.py +527 -0
  474. parrot/tools/pdfprint.py +1001 -0
  475. parrot/tools/powerbi.py +518 -0
  476. parrot/tools/powerpoint.py +1113 -0
  477. parrot/tools/pricestool.py +146 -0
  478. parrot/tools/products/__init__.py +246 -0
  479. parrot/tools/prophet_tool.py +171 -0
  480. parrot/tools/pythonpandas.py +630 -0
  481. parrot/tools/pythonrepl.py +910 -0
  482. parrot/tools/qsource.py +436 -0
  483. parrot/tools/querytoolkit.py +395 -0
  484. parrot/tools/quickeda.py +827 -0
  485. parrot/tools/resttool.py +553 -0
  486. parrot/tools/retail/__init__.py +0 -0
  487. parrot/tools/retail/bby.py +528 -0
  488. parrot/tools/sandboxtool.py +703 -0
  489. parrot/tools/sassie/__init__.py +352 -0
  490. parrot/tools/scraping/__init__.py +7 -0
  491. parrot/tools/scraping/docs/select.md +466 -0
  492. parrot/tools/scraping/documentation.md +1278 -0
  493. parrot/tools/scraping/driver.py +436 -0
  494. parrot/tools/scraping/models.py +576 -0
  495. parrot/tools/scraping/options.py +85 -0
  496. parrot/tools/scraping/orchestrator.py +517 -0
  497. parrot/tools/scraping/readme.md +740 -0
  498. parrot/tools/scraping/tool.py +3115 -0
  499. parrot/tools/seasonaldetection.py +642 -0
  500. parrot/tools/shell_tool/__init__.py +5 -0
  501. parrot/tools/shell_tool/actions.py +408 -0
  502. parrot/tools/shell_tool/engine.py +155 -0
  503. parrot/tools/shell_tool/models.py +322 -0
  504. parrot/tools/shell_tool/tool.py +442 -0
  505. parrot/tools/site_search.py +214 -0
  506. parrot/tools/textfile.py +418 -0
  507. parrot/tools/think.py +378 -0
  508. parrot/tools/toolkit.py +298 -0
  509. parrot/tools/webapp_tool.py +187 -0
  510. parrot/tools/whatif.py +1279 -0
  511. parrot/tools/workday/MULTI_WSDL_EXAMPLE.md +249 -0
  512. parrot/tools/workday/__init__.py +6 -0
  513. parrot/tools/workday/models.py +1389 -0
  514. parrot/tools/workday/tool.py +1293 -0
  515. parrot/tools/yfinance_tool.py +306 -0
  516. parrot/tools/zipcode.py +217 -0
  517. parrot/utils/__init__.py +2 -0
  518. parrot/utils/helpers.py +73 -0
  519. parrot/utils/parsers/__init__.py +5 -0
  520. parrot/utils/parsers/toml.c +12078 -0
  521. parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
  522. parrot/utils/parsers/toml.pyx +21 -0
  523. parrot/utils/toml.py +11 -0
  524. parrot/utils/types.cpp +20936 -0
  525. parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
  526. parrot/utils/types.pyx +213 -0
  527. parrot/utils/uv.py +11 -0
  528. parrot/version.py +10 -0
  529. parrot/yaml-rs/Cargo.lock +350 -0
  530. parrot/yaml-rs/Cargo.toml +19 -0
  531. parrot/yaml-rs/pyproject.toml +19 -0
  532. parrot/yaml-rs/python/yaml_rs/__init__.py +81 -0
  533. parrot/yaml-rs/src/lib.rs +222 -0
  534. requirements/docker-compose.yml +24 -0
  535. requirements/requirements-dev.txt +21 -0
parrot/tools/excel.py ADDED
@@ -0,0 +1,683 @@
1
+ """
2
+ MS Excel Tool migrated to use AbstractDocumentTool framework.
3
+ """
4
+ import io
5
+ from pathlib import Path
6
+ from typing import Any, Dict, List, Optional, Literal, Union
7
+ import pandas as pd
8
+ from openpyxl import Workbook, load_workbook
9
+ from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
10
+ from openpyxl.utils.dataframe import dataframe_to_rows
11
+ from odf.opendocument import OpenDocumentSpreadsheet
12
+ from odf.table import Table, TableRow, TableCell
13
+ from odf.text import P
14
+ from odf.style import Style, TableCellProperties, TextProperties
15
+ from pydantic import Field, field_validator, ConfigDict
16
+ from .document import AbstractDocumentTool, DocumentGenerationArgs
17
+
18
+
19
+ class ExcelArgs(DocumentGenerationArgs):
20
+ """Arguments schema for Excel/ODS Document generation."""
21
+
22
+ content: Union[pd.DataFrame, List[Dict[str, Any]]] = Field(
23
+ ...,
24
+ description="Pandas DataFrame or Dataset to export to Excel/ODS format"
25
+ )
26
+ sheet_name: str = Field(
27
+ "Sheet1",
28
+ description="Name of the worksheet"
29
+ )
30
+ template_file: Optional[str] = Field(
31
+ None,
32
+ description="Path to Excel/ODS template file to use as base"
33
+ )
34
+ output_format: Literal["excel", "ods"] = Field(
35
+ "excel",
36
+ description="Export format - 'excel' for .xlsx or 'ods' for OpenDocument"
37
+ )
38
+ header_styles: Optional[Dict[str, Any]] = Field(
39
+ None,
40
+ description="Dictionary of styles to apply to headers (font, color, etc.)"
41
+ )
42
+ data_styles: Optional[Dict[str, Any]] = Field(
43
+ None,
44
+ description="Dictionary of styles to apply to data cells"
45
+ )
46
+ auto_adjust_columns: bool = Field(
47
+ True,
48
+ description="Whether to auto-adjust column widths based on content"
49
+ )
50
+ freeze_header: bool = Field(
51
+ False,
52
+ description="Whether to freeze the header row"
53
+ )
54
+
55
+ model_config = ConfigDict(arbitrary_types_allowed=True)
56
+
57
+ @field_validator('content')
58
+ @classmethod
59
+ def validate_content(cls, v):
60
+ if isinstance(v, pd.DataFrame):
61
+ if v.empty:
62
+ raise ValueError("DataFrame content cannot be empty")
63
+ elif isinstance(v, list):
64
+ if not v:
65
+ raise ValueError("Content list cannot be empty")
66
+ if not all(isinstance(item, dict) for item in v):
67
+ raise ValueError("Content list must contain only dictionaries")
68
+ if v is None:
69
+ raise ValueError("content cannot be empty")
70
+ return v
71
+
72
+ @field_validator('sheet_name')
73
+ @classmethod
74
+ def validate_sheet_name(cls, v):
75
+ if not v or not v.strip():
76
+ raise ValueError("sheet_name cannot be empty")
77
+ # Excel sheet name limitations
78
+ invalid_chars = r'[:/\\?*\[\]]'
79
+ if any(char in v for char in invalid_chars):
80
+ raise ValueError(f"sheet_name contains invalid characters: {invalid_chars}")
81
+ if len(v) > 31:
82
+ raise ValueError("sheet_name cannot exceed 31 characters")
83
+ return v.strip()
84
+
85
+
86
+ class ExcelTool(AbstractDocumentTool):
87
+ """
88
+ Microsoft Excel/OpenDocument Spreadsheet Generation Tool.
89
+
90
+ This tool exports pandas DataFrames to Excel (.xlsx) or OpenDocument (.ods) files
91
+ with support for custom styling, templates, and advanced formatting features.
92
+
93
+ Features:
94
+ - Export DataFrames to Excel or ODS formats
95
+ - Custom header and data cell styling
96
+ - Template support for both formats
97
+ - Auto-adjusting column widths
98
+ - Header row freezing
99
+ - Professional spreadsheet formatting
100
+ - Comprehensive error handling and validation
101
+ """
102
+
103
+ name = "excel_generator"
104
+ description = (
105
+ "Export pandas DataFrames to Excel (.xlsx) or OpenDocument (.ods) files "
106
+ "with custom styling, templates, and professional formatting. "
107
+ "Supports both Excel and ODS formats with advanced styling options."
108
+ )
109
+ args_schema = ExcelArgs
110
+
111
+ # Document type configuration
112
+ document_type = "spreadsheet"
113
+ default_extension = "xlsx"
114
+ supported_extensions = [".xlsx", ".xls", ".ods"]
115
+
116
+ def __init__(
117
+ self,
118
+ templates_dir: Optional[Path] = None,
119
+ default_format: Literal["excel", "ods"] = "excel",
120
+ **kwargs
121
+ ):
122
+ """
123
+ Initialize the Excel Tool.
124
+
125
+ Args:
126
+ templates_dir: Directory containing Excel/ODS templates
127
+ default_format: Default output format ('excel' or 'ods')
128
+ **kwargs: Additional arguments for AbstractDocumentTool
129
+ """
130
+ super().__init__(templates_dir=templates_dir, **kwargs)
131
+ self.default_format = default_format
132
+
133
+ def _detect_output_format(self, output_format: str, filename: Optional[str] = None) -> str:
134
+ """Detect output format from format parameter or filename extension."""
135
+ if output_format:
136
+ return output_format
137
+
138
+ if filename:
139
+ ext = Path(filename).suffix.lower()
140
+ if ext in ['.ods']:
141
+ return 'ods'
142
+ elif ext in ['.xlsx', '.xls']:
143
+ return 'excel'
144
+
145
+ return self.default_format
146
+
147
+ def _parse_content_to_dataframe(self, content: Union[str, List[Dict], pd.DataFrame]) -> pd.DataFrame:
148
+ """
149
+ Parse content into a pandas DataFrame.
150
+
151
+ Args:
152
+ content: Can be a DataFrame, list of dictionaries, or JSON string
153
+
154
+ Returns:
155
+ pandas DataFrame
156
+ """
157
+ if isinstance(content, pd.DataFrame):
158
+ return content
159
+ elif isinstance(content, dict):
160
+ # Single dictionary, convert to DataFrame
161
+ return pd.DataFrame(content)
162
+ elif isinstance(content, list):
163
+ if not content:
164
+ raise ValueError("Content list cannot be empty")
165
+ if not all(isinstance(item, dict) for item in content):
166
+ raise ValueError("Content list must contain only dictionaries")
167
+ return pd.DataFrame(content)
168
+ elif isinstance(content, str):
169
+ try:
170
+ # Try to parse as JSON
171
+ data = self._json_decoder(content)
172
+ if isinstance(data, list):
173
+ return pd.DataFrame(data)
174
+ elif isinstance(data, dict):
175
+ # Single dictionary, wrap in list
176
+ return pd.DataFrame([data])
177
+ else:
178
+ raise ValueError("JSON content must be a list of objects or a single object")
179
+ except (TypeError, ValueError):
180
+ raise ValueError("String content must be valid JSON")
181
+ else:
182
+ raise ValueError(
183
+ "Content must be a pandas DataFrame, list of dictionaries, or JSON string"
184
+ )
185
+
186
+ def _get_extension_for_format(self, output_format: str) -> str:
187
+ """Get file extension for the specified format."""
188
+ return "ods" if output_format == "ods" else "xlsx"
189
+
190
+ def _create_excel_workbook(
191
+ self,
192
+ dataframe: pd.DataFrame,
193
+ sheet_name: str,
194
+ template_file: Optional[str] = None,
195
+ header_styles: Optional[Dict[str, Any]] = None,
196
+ data_styles: Optional[Dict[str, Any]] = None,
197
+ auto_adjust_columns: bool = True,
198
+ freeze_header: bool = False
199
+ ) -> Workbook:
200
+ """Create Excel workbook with DataFrame data and styling."""
201
+ # Load template or create new workbook
202
+ if template_file:
203
+ template_path = self._get_template_path(template_file)
204
+ if template_path and template_path.exists():
205
+ wb = load_workbook(str(template_path))
206
+ self.logger.info(f"Loaded Excel template: {template_path}")
207
+
208
+ # Clear existing data in the target sheet if it exists
209
+ if sheet_name in wb.sheetnames:
210
+ ws = wb[sheet_name]
211
+ ws.delete_rows(1, ws.max_row)
212
+ else:
213
+ ws = wb.create_sheet(sheet_name)
214
+ else:
215
+ self.logger.warning(f"Template not found: {template_file}, creating new workbook")
216
+ wb = Workbook()
217
+ ws = wb.active
218
+ ws.title = sheet_name
219
+ else:
220
+ wb = Workbook()
221
+ ws = wb.active
222
+ ws.title = sheet_name
223
+
224
+ # Convert DataFrame to rows
225
+ rows = dataframe_to_rows(dataframe, index=False, header=True)
226
+
227
+ # Add data to worksheet
228
+ for r_idx, row in enumerate(rows, 1):
229
+ for c_idx, value in enumerate(row, 1):
230
+ cell = ws.cell(row=r_idx, column=c_idx, value=value)
231
+
232
+ # Apply header styles
233
+ if r_idx == 1 and header_styles:
234
+ self._apply_excel_cell_style(cell, header_styles)
235
+ # Apply data styles
236
+ elif r_idx > 1 and data_styles:
237
+ self._apply_excel_cell_style(cell, data_styles)
238
+
239
+ # Apply default header styling if no custom styles provided
240
+ if not header_styles:
241
+ self._apply_default_excel_header_styles(ws, len(dataframe.columns))
242
+
243
+ # Auto-adjust column widths
244
+ if auto_adjust_columns:
245
+ self._adjust_excel_column_widths(ws)
246
+
247
+ # Freeze header row
248
+ if freeze_header:
249
+ ws.freeze_panes = ws['A2']
250
+
251
+ return wb
252
+
253
+ def _apply_excel_cell_style(self, cell, styles: Dict[str, Any]) -> None:
254
+ """Apply styles to an Excel cell."""
255
+ # Font styling
256
+ if any(key in styles for key in ['font_name', 'font_size', 'bold', 'italic', 'font_color']):
257
+ font_kwargs = {}
258
+ if 'font_name' in styles:
259
+ font_kwargs['name'] = styles['font_name']
260
+ if 'font_size' in styles:
261
+ font_kwargs['size'] = styles['font_size']
262
+ if 'bold' in styles:
263
+ font_kwargs['bold'] = styles['bold']
264
+ if 'italic' in styles:
265
+ font_kwargs['italic'] = styles['italic']
266
+ if 'font_color' in styles:
267
+ font_kwargs['color'] = styles['font_color']
268
+
269
+ cell.font = Font(**font_kwargs)
270
+
271
+ # Background color
272
+ if 'background_color' in styles:
273
+ cell.fill = PatternFill(
274
+ start_color=styles['background_color'],
275
+ end_color=styles['background_color'],
276
+ fill_type="solid"
277
+ )
278
+
279
+ # Alignment
280
+ if any(key in styles for key in ['horizontal', 'vertical', 'wrap_text']):
281
+ align_kwargs = {}
282
+ if 'horizontal' in styles:
283
+ align_kwargs['horizontal'] = styles['horizontal']
284
+ if 'vertical' in styles:
285
+ align_kwargs['vertical'] = styles['vertical']
286
+ if 'wrap_text' in styles:
287
+ align_kwargs['wrap_text'] = styles['wrap_text']
288
+
289
+ cell.alignment = Alignment(**align_kwargs)
290
+
291
+ # Borders
292
+ if 'border' in styles:
293
+ border_style = styles['border']
294
+ side = Side(style=border_style, color="000000")
295
+ cell.border = Border(left=side, right=side, top=side, bottom=side)
296
+
297
+ def _apply_default_excel_header_styles(self, ws, num_columns: int) -> None:
298
+ """Apply default styling to header row."""
299
+ header_font = Font(name='Calibri', size=12, bold=True, color="FFFFFF")
300
+ header_fill = PatternFill(start_color="366092", end_color="366092", fill_type="solid")
301
+ header_alignment = Alignment(horizontal="center", vertical="center")
302
+
303
+ for col in range(1, num_columns + 1):
304
+ cell = ws.cell(row=1, column=col)
305
+ cell.font = header_font
306
+ cell.fill = header_fill
307
+ cell.alignment = header_alignment
308
+
309
+ def _adjust_excel_column_widths(self, ws) -> None:
310
+ """Auto-adjust column widths based on content."""
311
+ for column in ws.columns:
312
+ max_length = 0
313
+ column_letter = column[0].column_letter
314
+
315
+ for cell in column:
316
+ try:
317
+ if len(str(cell.value)) > max_length:
318
+ max_length = len(str(cell.value))
319
+ except:
320
+ pass
321
+
322
+ adjusted_width = min(max_length + 2, 50) # Cap at 50 characters
323
+ ws.column_dimensions[column_letter].width = adjusted_width
324
+
325
+ def _create_ods_document(
326
+ self,
327
+ dataframe: pd.DataFrame,
328
+ sheet_name: str,
329
+ header_styles: Optional[Dict[str, Any]] = None,
330
+ data_styles: Optional[Dict[str, Any]] = None
331
+ ) -> OpenDocumentSpreadsheet:
332
+ """Create ODS document with DataFrame data and styling."""
333
+ # Create new ODS document
334
+ doc = OpenDocumentSpreadsheet()
335
+
336
+ # Create styles
337
+ header_style = self._create_ods_header_style(doc, header_styles)
338
+ data_style = self._create_ods_data_style(doc, data_styles)
339
+
340
+ # Create table (sheet)
341
+ table = Table(name=sheet_name)
342
+
343
+ # Add header row
344
+ header_row = TableRow()
345
+ for col_name in dataframe.columns:
346
+ cell = TableCell(stylename=header_style)
347
+ cell.addElement(P(text=str(col_name)))
348
+ header_row.addElement(cell)
349
+ table.addElement(header_row)
350
+
351
+ # Add data rows
352
+ for _, row in dataframe.iterrows():
353
+ data_row = TableRow()
354
+ for value in row:
355
+ cell = TableCell(stylename=data_style)
356
+ cell.addElement(P(text=str(value) if pd.notna(value) else ""))
357
+ data_row.addElement(cell)
358
+ table.addElement(data_row)
359
+
360
+ doc.spreadsheet.addElement(table)
361
+ return doc
362
+
363
+ def _create_ods_header_style(self, doc, custom_styles: Optional[Dict[str, Any]]) -> str:
364
+ """Create ODS style for headers."""
365
+ style = Style(name="HeaderStyle", family="table-cell")
366
+
367
+ # Default header properties
368
+ cell_props = TableCellProperties(
369
+ backgroundcolor="#366092",
370
+ border="1pt solid #000000"
371
+ )
372
+ text_props = TextProperties(
373
+ fontweight="bold",
374
+ color="#FFFFFF",
375
+ fontfamily="Calibri",
376
+ fontsize="12pt"
377
+ )
378
+
379
+ # Apply custom styles if provided
380
+ if custom_styles:
381
+ if 'background_color' in custom_styles:
382
+ cell_props.backgroundcolor = custom_styles['background_color']
383
+ if 'font_color' in custom_styles:
384
+ text_props.color = custom_styles['font_color']
385
+ if 'font_name' in custom_styles:
386
+ text_props.fontfamily = custom_styles['font_name']
387
+ if 'font_size' in custom_styles:
388
+ text_props.fontsize = f"{custom_styles['font_size']}pt"
389
+ if 'bold' in custom_styles:
390
+ text_props.fontweight = "bold" if custom_styles['bold'] else "normal"
391
+
392
+ style.addElement(cell_props)
393
+ style.addElement(text_props)
394
+ doc.styles.addElement(style)
395
+
396
+ return "HeaderStyle"
397
+
398
+ def _create_ods_data_style(self, doc, custom_styles: Optional[Dict[str, Any]]) -> str:
399
+ """Create ODS style for data cells."""
400
+ style = Style(name="DataStyle", family="table-cell")
401
+
402
+ # Default data properties
403
+ cell_props = TableCellProperties(border="1pt solid #CCCCCC")
404
+ text_props = TextProperties(
405
+ fontfamily="Calibri",
406
+ fontsize="11pt"
407
+ )
408
+
409
+ # Apply custom styles if provided
410
+ if custom_styles:
411
+ if 'background_color' in custom_styles:
412
+ cell_props.backgroundcolor = custom_styles['background_color']
413
+ if 'font_color' in custom_styles:
414
+ text_props.color = custom_styles['font_color']
415
+ if 'font_name' in custom_styles:
416
+ text_props.fontfamily = custom_styles['font_name']
417
+ if 'font_size' in custom_styles:
418
+ text_props.fontsize = f"{custom_styles['font_size']}pt"
419
+ if 'bold' in custom_styles:
420
+ text_props.fontweight = "bold" if custom_styles['bold'] else "normal"
421
+
422
+ style.addElement(cell_props)
423
+ style.addElement(text_props)
424
+ doc.styles.addElement(style)
425
+
426
+ return "DataStyle"
427
+
428
+ async def _generate_document_content(self, content: str, **kwargs) -> bytes:
429
+ """
430
+ Generate Excel/ODS document content from structured data.
431
+
432
+ Args:
433
+ content: Structured data - can be JSON string, list of dicts, or DataFrame
434
+ **kwargs: Additional arguments from ExcelArgs
435
+
436
+ Returns:
437
+ Excel/ODS document as bytes
438
+ """
439
+ try:
440
+ # Extract arguments
441
+ sheet_name = kwargs.get('sheet_name', 'Sheet1')
442
+ template_file = kwargs.get('template_file')
443
+ output_format = kwargs.get('output_format', 'excel')
444
+ header_styles = kwargs.get('header_styles')
445
+ data_styles = kwargs.get('data_styles')
446
+ auto_adjust_columns = kwargs.get('auto_adjust_columns', True)
447
+ freeze_header = kwargs.get('freeze_header', False)
448
+
449
+ # Parse content to DataFrame
450
+ dataframe = self._parse_content_to_dataframe(content)
451
+
452
+ self.logger.info(
453
+ f"Generating {output_format} document with {len(dataframe)} rows and "
454
+ f"{len(dataframe.columns)} columns"
455
+ )
456
+
457
+ # Create document based on format
458
+ doc_bytes = io.BytesIO()
459
+
460
+ if output_format == "ods":
461
+ # Create ODS document
462
+ doc = self._create_ods_document(
463
+ dataframe=dataframe,
464
+ sheet_name=sheet_name,
465
+ header_styles=header_styles,
466
+ data_styles=data_styles
467
+ )
468
+ doc.save(doc_bytes)
469
+ else:
470
+ # Create Excel document
471
+ wb = self._create_excel_workbook(
472
+ dataframe=dataframe,
473
+ sheet_name=sheet_name,
474
+ template_file=template_file,
475
+ header_styles=header_styles,
476
+ data_styles=data_styles,
477
+ auto_adjust_columns=auto_adjust_columns,
478
+ freeze_header=freeze_header
479
+ )
480
+ wb.save(doc_bytes)
481
+
482
+ doc_bytes.seek(0)
483
+ return doc_bytes.getvalue()
484
+
485
+ except Exception as e:
486
+ self.logger.error(f"Error generating {output_format} document: {e}")
487
+ raise
488
+
489
+ async def _execute(
490
+ self,
491
+ content: Union[str, List[Dict], pd.DataFrame],
492
+ sheet_name: str = "Sheet1",
493
+ template_file: Optional[str] = None,
494
+ output_format: Literal["excel", "ods"] = "excel",
495
+ header_styles: Optional[Dict[str, Any]] = None,
496
+ data_styles: Optional[Dict[str, Any]] = None,
497
+ auto_adjust_columns: bool = True,
498
+ freeze_header: bool = False,
499
+ output_filename: Optional[str] = None,
500
+ file_prefix: str = "spreadsheet",
501
+ output_dir: Optional[str] = None,
502
+ overwrite_existing: bool = False,
503
+ **kwargs
504
+ ) -> Dict[str, Any]:
505
+ """
506
+ Execute Excel/ODS document generation (AbstractTool interface).
507
+
508
+ Args:
509
+ content: Structured data - DataFrame, list of dicts, or JSON string
510
+ sheet_name: Name of the worksheet
511
+ template_file: Excel/ODS template file path
512
+ output_format: Export format ('excel' or 'ods')
513
+ header_styles: Custom header styling
514
+ data_styles: Custom data cell styling
515
+ auto_adjust_columns: Whether to auto-adjust column widths
516
+ freeze_header: Whether to freeze the header row
517
+ output_filename: Custom filename (without extension)
518
+ file_prefix: Prefix for auto-generated filenames
519
+ output_dir: Custom output directory
520
+ overwrite_existing: Whether to overwrite existing files
521
+ **kwargs: Additional arguments
522
+
523
+ Returns:
524
+ Dictionary with document generation results
525
+ """
526
+ try:
527
+ # Parse content to get DataFrame info for logging
528
+ dataframe = self._parse_content_to_dataframe(content)
529
+
530
+ # Detect format and set appropriate extension
531
+ detected_format = self._detect_output_format(output_format, output_filename)
532
+ extension = self._get_extension_for_format(detected_format)
533
+
534
+ self.logger.info(
535
+ f"Starting {detected_format.upper()} document generation with "
536
+ f"{len(dataframe)} rows and {len(dataframe.columns)} columns"
537
+ )
538
+
539
+ # Use the safe document creation workflow
540
+ result = await self._create_document_safely(
541
+ content=dataframe,
542
+ output_filename=output_filename,
543
+ file_prefix=file_prefix,
544
+ output_dir=output_dir,
545
+ overwrite_existing=overwrite_existing or self.overwrite_existing,
546
+ extension=extension,
547
+ sheet_name=sheet_name,
548
+ template_file=template_file,
549
+ output_format=detected_format,
550
+ header_styles=header_styles,
551
+ data_styles=data_styles,
552
+ auto_adjust_columns=auto_adjust_columns,
553
+ freeze_header=freeze_header
554
+ )
555
+
556
+ if result['status'] == 'success':
557
+ # Add Excel-specific metadata
558
+ result['metadata'].update({
559
+ 'format': detected_format,
560
+ 'sheet_name': sheet_name,
561
+ 'rows': len(dataframe),
562
+ 'columns': len(dataframe.columns),
563
+ 'column_names': list(dataframe.columns)
564
+ })
565
+
566
+ self.logger.info(
567
+ f"{detected_format.upper()} document created successfully: "
568
+ f"{result['metadata']['filename']}"
569
+ )
570
+
571
+ return result
572
+
573
+ except Exception as e:
574
+ self.logger.error(f"Error in Excel document generation: {e}")
575
+ raise
576
+
577
+ # Convenience methods for direct DataFrame export
578
+ async def export_dataframe(
579
+ self,
580
+ dataframe: pd.DataFrame,
581
+ output_format: Literal["excel", "ods"] = "excel",
582
+ **kwargs
583
+ ) -> Dict[str, Any]:
584
+ """
585
+ Convenience method to directly export a DataFrame.
586
+
587
+ Args:
588
+ dataframe: DataFrame to export
589
+ output_format: Export format
590
+ **kwargs: Additional arguments for _execute
591
+
592
+ Returns:
593
+ Dictionary with export results
594
+ """
595
+ return await self._execute(
596
+ content=dataframe,
597
+ output_format=output_format,
598
+ **kwargs
599
+ )
600
+
601
+ async def export_data(
602
+ self,
603
+ data: Union[List[Dict], pd.DataFrame, str],
604
+ output_format: Literal["excel", "ods"] = "excel",
605
+ **kwargs
606
+ ) -> Dict[str, Any]:
607
+ """
608
+ Convenience method to export various data formats.
609
+
610
+ Args:
611
+ data: Data to export (DataFrame, list of dicts, or JSON string)
612
+ output_format: Export format
613
+ **kwargs: Additional arguments for _execute
614
+
615
+ Returns:
616
+ Dictionary with export results
617
+ """
618
+ return await self._execute(
619
+ content=data,
620
+ output_format=output_format,
621
+ **kwargs
622
+ )
623
+
624
+ def get_format_info(self) -> Dict[str, Any]:
625
+ """Get information about supported formats."""
626
+ return {
627
+ "supported_formats": ["excel", "ods"],
628
+ "excel_extensions": [".xlsx", ".xls"],
629
+ "ods_extensions": [".ods"],
630
+ "default_format": self.default_format,
631
+ "features": {
632
+ "templates": True,
633
+ "custom_styling": True,
634
+ "auto_column_width": True,
635
+ "freeze_panes": True,
636
+ "multiple_sheets": False # Could be extended in future
637
+ }
638
+ }
639
+
640
+
641
+ class DataFrameToExcelTool(ExcelTool):
642
+ """
643
+ Simplified Excel tool that focuses purely on DataFrame export.
644
+
645
+ This is a convenience wrapper around ExcelTool for users who primarily
646
+ need to export DataFrames without complex document features.
647
+ """
648
+
649
+ name = "dataframe_to_excel"
650
+ description = (
651
+ "Simple tool to export pandas DataFrames to Excel or ODS files. "
652
+ "Focused on quick DataFrame export with minimal configuration."
653
+ )
654
+
655
+ async def quick_export(
656
+ self,
657
+ data: Union[pd.DataFrame, List[Dict], str],
658
+ filename: Optional[str] = None,
659
+ format: Literal["excel", "ods"] = "excel"
660
+ ) -> str:
661
+ """
662
+ Quick export method that returns just the file path.
663
+
664
+ Args:
665
+ data: Data to export (DataFrame, list of dicts, or JSON string)
666
+ filename: Optional filename
667
+ format: Export format
668
+
669
+ Returns:
670
+ Path to the created file
671
+ """
672
+ result = await self.export_data(
673
+ data=data,
674
+ output_filename=filename,
675
+ output_format=format
676
+ )
677
+
678
+ if result['status'] == 'success':
679
+ return result['metadata']['file_path']
680
+ else:
681
+ raise Exception(
682
+ f"Export failed: {result.get('error', 'Unknown error')}"
683
+ )
@@ -0,0 +1,13 @@
1
+ from .abstract import FileManagerInterface, FileMetadata
2
+ from .local import LocalFileManager
3
+ from .s3 import S3FileManager
4
+ from .tmp import TempFileManager
5
+ from .gcs import GCSFileManager
6
+ from .tool import FileManagerTool
7
+
8
+
9
+ __all__ = (
10
+ "FileManagerInterface",
11
+ "FileMetadata",
12
+ "FileManagerTool",
13
+ )