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/math.py ADDED
@@ -0,0 +1,152 @@
1
+ from typing import Dict, Any, Optional
2
+ import math as mathlib
3
+ from pydantic import BaseModel, Field, field_validator
4
+ from .abstract import AbstractTool
5
+
6
+
7
+ # MathTool Arguments Schema
8
+ class MathToolArgs(BaseModel):
9
+ """Arguments schema for MathTool."""
10
+ a: float = Field(description="The number for unary operations, or the first number for binary operations.")
11
+ operation: str = Field(
12
+ description="Mathematical operation. Supports: add, subtract, multiply, divide, sqrt."
13
+ )
14
+ b: Optional[float] = Field(
15
+ default=None,
16
+ description="The second number for binary operations. Not used for unary operations like square root."
17
+ )
18
+
19
+
20
+ @field_validator('operation')
21
+ @classmethod
22
+ def validate_operation(cls, v: str) -> str:
23
+ """Normalize operation names to internal format."""
24
+ # Mapping of various operation names to internal names
25
+ operation_mapping = {
26
+ # Standard names
27
+ 'add': 'add',
28
+ 'subtract': 'subtract',
29
+ 'multiply': 'multiply',
30
+ 'divide': 'divide',
31
+ # Alternative names
32
+ 'addition': 'add',
33
+ 'subtraction': 'subtract',
34
+ 'multiplication': 'multiply',
35
+ 'division': 'divide',
36
+ # Math symbols
37
+ '+': 'add',
38
+ '-': 'subtract',
39
+ '*': 'multiply',
40
+ '/': 'divide',
41
+ '÷': 'divide',
42
+ '×': 'multiply',
43
+ # Common variations
44
+ 'plus': 'add',
45
+ 'minus': 'subtract',
46
+ 'times': 'multiply',
47
+ 'sum': 'add',
48
+ 'difference': 'subtract',
49
+ 'product': 'multiply',
50
+ 'quotient': 'divide',
51
+ 'sqrt': 'sqrt',
52
+ 'square_root': 'sqrt',
53
+ 'square root': 'sqrt'
54
+ }
55
+
56
+ normalized = v.lower().strip()
57
+ if normalized in operation_mapping:
58
+ return operation_mapping[normalized]
59
+
60
+ # If not found, provide helpful error message
61
+ valid_operations = list(set(operation_mapping.values()))
62
+ raise ValueError(
63
+ f"Unsupported operation: '{v}'. "
64
+ f"Supported operations: {', '.join(valid_operations)} "
65
+ f"or their aliases: {', '.join(operation_mapping.keys())}"
66
+ )
67
+
68
+ class MathTool(AbstractTool):
69
+ """A tool for performing basic arithmetic operations."""
70
+
71
+ name = "MathTool"
72
+ description = "Performs basic arithmetic operations: addition, subtraction, multiplication, division and square root. Accepts various operation names like 'add', 'addition', '+', 'plus', etc."
73
+ args_schema = MathToolArgs
74
+
75
+ def __init__(self, **kwargs):
76
+ super().__init__(**kwargs)
77
+
78
+ async def _execute(self, a: float, operation: str = 'add', b: float = None, **kwargs) -> Dict[str, Any]:
79
+ """
80
+ Execute the mathematical operation.
81
+
82
+ Args:
83
+ a: First number
84
+ b: Second number
85
+ operation: Operation to perform (already normalized by validator)
86
+
87
+ Returns:
88
+ Dictionary with the result
89
+ """
90
+ unary_operations = {
91
+ "sqrt": self.sqrt
92
+ }
93
+ binary_operations = {
94
+ "add": self.add,
95
+ "subtract": self.subtract,
96
+ "multiply": self.multiply,
97
+ "divide": self.divide
98
+ }
99
+
100
+ if operation in unary_operations:
101
+ result = unary_operations[operation](a)
102
+ operands = [a]
103
+ elif operation in binary_operations:
104
+ if b is None:
105
+ raise ValueError(f"Operation '{operation}' requires a second number ('b').")
106
+ result = binary_operations[operation](a, b)
107
+ operands = [a, b]
108
+ else:
109
+ raise ValueError(f"Unsupported operation: {operation}")
110
+
111
+ return {
112
+ "operation": operation,
113
+ "operands": operands,
114
+ "result": result,
115
+ "expression": self._format_expression(a, operation, result, b)
116
+ }
117
+
118
+ def add(self, a: float, b: float) -> float:
119
+ """Add two numbers."""
120
+ return a + b
121
+
122
+ def subtract(self, a: float, b: float) -> float:
123
+ """Subtract two numbers."""
124
+ return a - b
125
+
126
+ def multiply(self, a: float, b: float) -> float:
127
+ """Multiply two numbers."""
128
+ return a * b
129
+
130
+ def divide(self, a: float, b: float) -> float:
131
+ """Divide two numbers."""
132
+ if b == 0:
133
+ raise ValueError("Cannot divide by zero")
134
+ return a / b
135
+
136
+ def sqrt(self, a: float) -> float:
137
+ """Calculate the square root of a number."""
138
+ if a < 0:
139
+ raise ValueError("Cannot calculate the square root of a negative number.")
140
+ return mathlib.sqrt(a)
141
+
142
+ def _format_expression(self, a: float, operation: str, result: float, b: Optional[float] = None) -> str:
143
+ """Format the mathematical expression as a string."""
144
+ if b is not None: # Binary operation
145
+ operators = {"add": "+", "subtract": "-", "multiply": "*", "divide": "/"}
146
+ operator = operators.get(operation, operation)
147
+ return f"{a} {operator} {b} = {result}"
148
+ else: # Unary operation
149
+ if operation == 'sqrt':
150
+ return f"sqrt({a}) = {result}"
151
+ # Add other unary operations here if needed
152
+ return f"{operation}({a}) = {result}"
@@ -0,0 +1,476 @@
1
+ """Metadata tool for describing DataFrame schemas to the LLM."""
2
+ from typing import Any, Dict, Optional
3
+ from pydantic import Field
4
+ import numpy as np
5
+ import pandas as pd
6
+ from .abstract import AbstractTool, AbstractToolArgsSchema, ToolResult
7
+
8
+
9
+ class MetadataToolArgs(AbstractToolArgsSchema):
10
+ """Arguments for the MetadataTool."""
11
+
12
+ dataframe: Optional[str] = Field(
13
+ default=None,
14
+ description="Name of the DataFrame to inspect"
15
+ )
16
+ column: Optional[str] = Field(
17
+ default=None,
18
+ description="Specific column within the DataFrame to describe"
19
+ )
20
+ include_eda: bool = Field(
21
+ default=True,
22
+ description="Add Exploratory data analysis summary (statistics, missing values, memory usage)"
23
+ )
24
+ include_samples: bool = Field(
25
+ default=True,
26
+ description="Include sample rows from the DataFrame"
27
+ )
28
+ include_column_stats: bool = Field(
29
+ default=False,
30
+ description="Include detailed statistics for numeric and categorical columns"
31
+ )
32
+ include_eda: bool = Field(
33
+ default=False,
34
+ description="Add Exploratory data analysis summary (statistics, missing values, memory usage)"
35
+ )
36
+ include_samples: bool = Field(
37
+ default=False,
38
+ description="Include sample rows from the DataFrame"
39
+ )
40
+ include_column_stats: bool = Field(
41
+ default=False,
42
+ description="Include detailed statistics for numeric and categorical columns"
43
+ )
44
+ column: str | None = Field(
45
+ default=None,
46
+ description="Specific column within the DataFrame to describe"
47
+ )
48
+
49
+
50
+
51
+ class MetadataTool(AbstractTool):
52
+ """
53
+ Expose DataFrame metadata with comprehensive EDA capabilities.
54
+
55
+ Provides:
56
+ - DataFrame schemas (columns, dtypes, shapes)
57
+ - EDA summaries (row counts, column types, missing values, memory usage)
58
+ - Sample rows for quick data inspection
59
+ - Detailed column statistics (optional)
60
+ """
61
+
62
+ name = "dataframe_metadata"
63
+ description = (
64
+ "Retrieve comprehensive metadata about a single DataFrame including schema, "
65
+ "exploratory data analysis (EDA) statistics, column descriptions, and sample rows. "
66
+ "Use this tool to understand DataFrame structure, data types, missing values, "
67
+ "and basic statistics before performing analysis. Call this tool for one DataFrame at a time."
68
+ )
69
+ args_schema = MetadataToolArgs
70
+
71
+ def __init__(
72
+ self,
73
+ metadata: Optional[Dict[str, Dict[str, Any]]] = None,
74
+ alias_map: Optional[Dict[str, str]] = None,
75
+ dataframes: Optional[Dict[str, pd.DataFrame]] = None,
76
+ **kwargs
77
+ ) -> None:
78
+ """
79
+ Initialize MetadataTool.
80
+
81
+ Args:
82
+ metadata: Pre-computed metadata dictionary
83
+ alias_map: Mapping of DataFrame names to standardized aliases (df1, df2, etc.)
84
+ dataframes: Reference to actual DataFrames for dynamic EDA generation
85
+ **kwargs: Additional tool configuration
86
+ """
87
+ super().__init__(**kwargs)
88
+ self.metadata: Dict[str, Dict[str, Any]] = metadata or {}
89
+ self.alias_map: Dict[str, str] = alias_map or {}
90
+ self.dataframes: Dict[str, pd.DataFrame] = dataframes or {}
91
+
92
+ def update_metadata(
93
+ self,
94
+ metadata: Dict[str, Dict[str, Any]],
95
+ alias_map: Optional[Dict[str, str]] = None,
96
+ dataframes: Optional[Dict[str, pd.DataFrame]] = None
97
+ ) -> None:
98
+ """
99
+ Update the internal metadata dictionary, alias map, and dataframes.
100
+
101
+ Args:
102
+ metadata: New metadata dictionary
103
+ alias_map: New alias mapping
104
+ dataframes: New DataFrame references
105
+ """
106
+ self.metadata = metadata or {}
107
+ self.alias_map = alias_map or {}
108
+ if dataframes is not None:
109
+ self.dataframes = dataframes
110
+
111
+ async def _execute(
112
+ self,
113
+ dataframe: Optional[str] = None,
114
+ column: Optional[str] = None,
115
+ include_eda: bool = True,
116
+ include_samples: bool = True,
117
+ include_column_stats: bool = False,
118
+ **_: Any
119
+ ) -> ToolResult:
120
+ """
121
+ Execute metadata retrieval with optional EDA generation.
122
+
123
+ Args:
124
+ dataframe: Name or alias of the DataFrame to inspect
125
+ column: Specific column to describe
126
+ include_eda: Generate EDA summary dynamically
127
+ include_samples: Include sample rows
128
+ include_column_stats: Include detailed column statistics
129
+
130
+ Returns:
131
+ ToolResult with metadata and optional EDA information
132
+ """
133
+ if not self.metadata:
134
+ return ToolResult(
135
+ status="success",
136
+ result={"message": "No metadata available. No DataFrames are currently loaded."},
137
+ metadata={"tool_name": self.name}
138
+ )
139
+
140
+ if dataframe:
141
+ try:
142
+ result = self._describe_dataframe(
143
+ dataframe,
144
+ column,
145
+ include_eda=include_eda,
146
+ include_samples=include_samples,
147
+ include_column_stats=include_column_stats
148
+ )
149
+ except ValueError as exc:
150
+ return ToolResult(
151
+ status="error",
152
+ result=None,
153
+ error=str(exc),
154
+ metadata={
155
+ "tool_name": self.name,
156
+ "dataframe": dataframe,
157
+ "column": column
158
+ }
159
+ )
160
+ else:
161
+ # List all available DataFrames
162
+ result = self._list_available_dataframes()
163
+
164
+ return ToolResult(
165
+ status="success",
166
+ result=result,
167
+ metadata={
168
+ "tool_name": self.name,
169
+ "dataframe": dataframe,
170
+ "column": column,
171
+ "include_eda": include_eda
172
+ }
173
+ )
174
+
175
+ def _list_available_dataframes(self) -> Dict[str, Any]:
176
+ """List all available DataFrames with basic information."""
177
+ return {
178
+ "message": "Available DataFrames for analysis",
179
+ "total_dataframes": len(self.metadata),
180
+ "dataframes": [
181
+ {
182
+ "name": name,
183
+ "standardized_name": self.alias_map.get(name),
184
+ "description": meta.get('description'),
185
+ "shape": meta.get('shape'),
186
+ "row_count": meta.get('row_count'),
187
+ "column_count": meta.get('column_count'),
188
+ "columns": list(meta.get('columns', {}).keys()),
189
+ "memory_mb": meta.get('memory_usage_mb')
190
+ }
191
+ for name, meta in self.metadata.items()
192
+ ]
193
+ }
194
+
195
+ def _describe_dataframe(
196
+ self,
197
+ dataframe: str,
198
+ column: Optional[str] = None,
199
+ include_eda: bool = True,
200
+ include_samples: bool = True,
201
+ include_column_stats: bool = False
202
+ ) -> Dict[str, Any]:
203
+ """
204
+ Describe a DataFrame and optionally a specific column.
205
+
206
+ Args:
207
+ dataframe: DataFrame name or alias
208
+ column: Optional specific column to describe
209
+ include_eda: Generate dynamic EDA summary
210
+ include_samples: Include sample rows
211
+ include_column_stats: Include detailed column statistics
212
+
213
+ Returns:
214
+ Comprehensive DataFrame or column description
215
+ """
216
+ df_name = self._resolve_dataframe_name(dataframe)
217
+ df_meta = self.metadata.get(df_name)
218
+
219
+ if not df_meta:
220
+ raise ValueError(
221
+ f"DataFrame '{dataframe}' metadata not found. "
222
+ f"Available DataFrames: {list(self.metadata.keys())}"
223
+ )
224
+
225
+ # Handle single column request
226
+ if column:
227
+ return self._describe_column(df_name, column, df_meta)
228
+
229
+ # Build comprehensive DataFrame description
230
+ response = {
231
+ "dataframe": df_name,
232
+ "standardized_name": self.alias_map.get(df_name),
233
+ "description": df_meta.get('description'),
234
+ "shape": df_meta.get('shape'),
235
+ "row_count": df_meta.get('row_count'),
236
+ "column_count": df_meta.get('column_count'),
237
+ }
238
+
239
+ # Add pre-computed metadata fields
240
+ response |= {
241
+ key: value
242
+ for key, value in df_meta.items()
243
+ if key not in ['name', 'columns', 'sample_data', 'eda_summary']
244
+ }
245
+
246
+ # Include column information
247
+ response['columns'] = df_meta.get('columns', {})
248
+
249
+ # Generate dynamic EDA if requested
250
+ if include_eda:
251
+ include_samples = True
252
+ include_column_stats = True
253
+ if eda_summary := self._generate_eda_summary(df_name):
254
+ # Override with dynamic EDA if available
255
+ response['eda_summary'] = eda_summary
256
+
257
+ # Include sample rows if requested
258
+ if include_samples:
259
+ if sample_data := df_meta.get('sample_data', []):
260
+ response['sample_rows'] = sample_data
261
+
262
+ # Include detailed column statistics if requested
263
+ if include_column_stats:
264
+ if column_stats := self._generate_column_statistics(df_name):
265
+ response['column_statistics'] = column_stats
266
+
267
+ return response
268
+
269
+ def _describe_column(
270
+ self,
271
+ df_name: str,
272
+ column: str,
273
+ df_meta: Dict[str, Any]
274
+ ) -> Dict[str, Any]:
275
+ """
276
+ Describe a specific column with detailed information.
277
+
278
+ Args:
279
+ df_name: DataFrame name
280
+ column: Column name
281
+ df_meta: DataFrame metadata
282
+
283
+ Returns:
284
+ Column description dictionary
285
+ """
286
+ column_meta = df_meta.get('columns', {}).get(column)
287
+
288
+ if not column_meta:
289
+ available_columns = list(df_meta.get('columns', {}).keys())
290
+ raise ValueError(
291
+ f"Column '{column}' not found in DataFrame '{df_name}'. "
292
+ f"Available columns: {available_columns}"
293
+ )
294
+
295
+ response = {
296
+ "dataframe": df_name,
297
+ "standardized_name": self.alias_map.get(df_name),
298
+ "column": column,
299
+ "metadata": column_meta
300
+ }
301
+
302
+ # Add column-specific statistics if DataFrame is available
303
+ df = self.dataframes.get(df_name)
304
+ if df is not None and column in df.columns:
305
+ response['statistics'] = self._compute_column_stats(df[column])
306
+
307
+ return response
308
+
309
+ def _generate_eda_summary(self, df_name: str) -> Optional[Dict[str, Any]]:
310
+ """
311
+ Generate comprehensive exploratory data analysis summary for a DataFrame.
312
+
313
+ This method generates EDA statistics dynamically from the actual DataFrame
314
+ if available, or falls back to pre-computed metadata.
315
+
316
+ Args:
317
+ df_name: DataFrame identifier
318
+
319
+ Returns:
320
+ Dictionary containing EDA summary or None if unavailable
321
+ """
322
+ df = self.dataframes.get(df_name)
323
+
324
+ if df is None:
325
+ # Fallback to pre-computed EDA if available
326
+ df_meta = self.metadata.get(df_name, {})
327
+ if 'eda_summary' in df_meta:
328
+ return {"summary_text": df_meta['eda_summary']}
329
+ return None
330
+
331
+ # Generate fresh EDA from DataFrame
332
+ numeric_cols = df.select_dtypes(include=[np.number]).columns
333
+ categorical_cols = df.select_dtypes(include=['object', 'category']).columns
334
+ datetime_cols = df.select_dtypes(include=['datetime64']).columns
335
+
336
+ # Missing data analysis
337
+ missing = df.isnull().sum()
338
+ total_missing = int(missing.sum())
339
+ missing_percentage = float(missing.sum() / df.size * 100) if df.size > 0 else 0.0
340
+
341
+ # Memory usage
342
+ memory_mb = float(df.memory_usage(deep=True).sum() / 1024 / 1024)
343
+
344
+ # Columns with missing values
345
+ columns_with_missing = [
346
+ {
347
+ "column": col,
348
+ "missing_count": int(missing[col]),
349
+ "missing_percentage": float(missing[col] / len(df) * 100) if len(df) > 0 else 0.0
350
+ }
351
+ for col in df.columns
352
+ if missing[col] > 0
353
+ ]
354
+
355
+ return {
356
+ "basic_info": {
357
+ "total_rows": len(df),
358
+ "total_columns": len(df.columns),
359
+ "numeric_columns": len(numeric_cols),
360
+ "categorical_columns": len(categorical_cols),
361
+ "datetime_columns": len(datetime_cols),
362
+ "memory_usage_mb": round(memory_mb, 2),
363
+ },
364
+ "missing_data": {
365
+ "total_missing": total_missing,
366
+ "missing_percentage": round(missing_percentage, 2),
367
+ "columns_with_missing": columns_with_missing
368
+ },
369
+ "data_quality": {
370
+ "duplicate_rows": int(df.duplicated().sum()),
371
+ "completeness_percentage": round((1 - missing_percentage / 100) * 100, 2)
372
+ }
373
+ }
374
+
375
+ def _generate_column_statistics(self, df_name: str) -> Optional[Dict[str, Any]]:
376
+ """
377
+ Generate detailed statistics for all columns in a DataFrame.
378
+
379
+ Args:
380
+ df_name: DataFrame identifier
381
+
382
+ Returns:
383
+ Dictionary with column statistics or None
384
+ """
385
+ df = self.dataframes.get(df_name)
386
+ if df is None:
387
+ return None
388
+
389
+ numeric_cols = df.select_dtypes(include=[np.number]).columns
390
+ categorical_cols = df.select_dtypes(include=['object', 'category']).columns
391
+
392
+ stats = {
393
+ "numeric_columns": {},
394
+ "categorical_columns": {}
395
+ }
396
+
397
+ # Numeric column statistics
398
+ for col in numeric_cols:
399
+ stats["numeric_columns"][col] = self._compute_column_stats(df[col])
400
+
401
+ # Categorical column statistics
402
+ for col in categorical_cols:
403
+ value_counts = df[col].value_counts()
404
+ stats["categorical_columns"][col] = {
405
+ "unique_values": int(df[col].nunique()),
406
+ "most_common": value_counts.head(10).to_dict(),
407
+ "null_count": int(df[col].isnull().sum())
408
+ }
409
+
410
+ return stats
411
+
412
+ def _compute_column_stats(self, series: pd.Series) -> Dict[str, Any]:
413
+ """
414
+ Compute statistics for a single column/series.
415
+
416
+ Args:
417
+ series: pandas Series to analyze
418
+
419
+ Returns:
420
+ Dictionary of column statistics
421
+ """
422
+ stats = {
423
+ "dtype": str(series.dtype),
424
+ "null_count": int(series.isnull().sum()),
425
+ "null_percentage": round(float(series.isnull().sum() / len(series) * 100), 2) if len(series) > 0 else 0.0
426
+ }
427
+
428
+ if pd.api.types.is_numeric_dtype(series):
429
+ # Numeric statistics
430
+ stats |= {
431
+ "mean": None if series.empty else float(series.mean()),
432
+ "median": None if series.empty else float(series.median()),
433
+ "std": None if series.empty else float(series.std()),
434
+ "min": None if series.empty else float(series.min()),
435
+ "max": None if series.empty else float(series.max()),
436
+ "q25": None if series.empty else float(series.quantile(0.25)),
437
+ "q75": None if series.empty else float(series.quantile(0.75)),
438
+ }
439
+ else:
440
+ # Categorical/string statistics
441
+ stats |= {
442
+ "unique_values": int(series.nunique()),
443
+ "most_common": None if series.mode().empty else str(series.mode().iloc[0]),
444
+ }
445
+
446
+ return stats
447
+
448
+ def _resolve_dataframe_name(self, identifier: str) -> str:
449
+ """
450
+ Resolve either a standardized key (df1) or original name to metadata key.
451
+
452
+ Args:
453
+ identifier: DataFrame name or alias
454
+
455
+ Returns:
456
+ Resolved DataFrame name
457
+ """
458
+ # Direct match
459
+ if identifier in self.metadata:
460
+ return identifier
461
+
462
+ # Alias match (df1 -> actual_name)
463
+ for name, alias in self.alias_map.items():
464
+ if alias == identifier:
465
+ return name
466
+
467
+ # Case-insensitive match
468
+ identifier_lower = identifier.lower()
469
+ return next(
470
+ (
471
+ name
472
+ for name in self.metadata.keys()
473
+ if name.lower() == identifier_lower
474
+ ),
475
+ identifier,
476
+ )