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
@@ -0,0 +1,630 @@
1
+ import contextlib
2
+ from typing import Optional, Dict, Any, List
3
+ import numpy as np
4
+ import pandas as pd
5
+ from .pythonrepl import (
6
+ PythonREPLTool,
7
+ PythonREPLArgs,
8
+ brace_escape
9
+ )
10
+
11
+ class PythonPandasTool(PythonREPLTool):
12
+ """
13
+ Python Pandas Tool with pre-loaded DataFrames and enhanced data science capabilities.
14
+
15
+ Extends PythonREPLTool to provide:
16
+ - Automatic DataFrame binding with ORIGINAL names as primary identifiers
17
+ - Standardized aliases (df1, df2, etc.) as convenience references
18
+ - DataFrame information generation and guides
19
+ - Enhanced data exploration utilities
20
+ - Safe DataFrame operations
21
+ """
22
+
23
+ name = "python_repl_pandas"
24
+ description = "Execute Python code with pre-loaded DataFrames and enhanced pandas capabilities"
25
+ args_schema = PythonREPLArgs
26
+
27
+ # Available plotting libraries configuration
28
+ PLOTTING_LIBRARIES = {
29
+ 'matplotlib': {
30
+ 'import_as': 'plt',
31
+ 'import_statement': 'import matplotlib.pyplot as plt',
32
+ 'description': 'Traditional plotting library with extensive customization',
33
+ 'best_for': ['statistical plots', 'publication-quality figures', 'fine-grained control'],
34
+ 'examples': [
35
+ 'plt.figure(figsize=(10, 6))',
36
+ 'plt.plot(df1["column"], df1["value"])',
37
+ 'plt.hist(df1["numeric_column"], bins=20)',
38
+ 'plt.scatter(df1["x"], df1["y"])',
39
+ 'save_current_plot("my_plot.png")'
40
+ ]
41
+ },
42
+ 'plotly': {
43
+ 'import_as': 'px, go, pio',
44
+ 'import_statement': 'import plotly.express as px\nimport plotly.graph_objects as go\nimport plotly.io as pio',
45
+ 'description': 'Interactive web-based plotting library',
46
+ 'best_for': ['interactive plots', 'dashboards', 'web applications'],
47
+ 'examples': [
48
+ 'fig = px.scatter(df1, x="column1", y="column2", color="category")',
49
+ 'fig = px.histogram(df1, x="numeric_column")',
50
+ 'fig = go.Figure(data=go.Bar(x=df1["category"], y=df1["value"]))',
51
+ 'fig.show() # Note: may not display in REPL, use fig.write_html("plot.html")'
52
+ ]
53
+ },
54
+ 'bokeh': {
55
+ 'import_as': 'bokeh',
56
+ 'import_statement': 'from bokeh.plotting import figure, show, output_file\nfrom bokeh.models import ColumnDataSource',
57
+ 'description': 'Interactive visualization library for web browsers',
58
+ 'best_for': ['large datasets', 'real-time streaming', 'web deployment'],
59
+ 'examples': [
60
+ 'p = figure(title="My Plot", x_axis_label="X", y_axis_label="Y")',
61
+ 'p.circle(df1["x"], df1["y"], size=10)',
62
+ 'output_file("plot.html")',
63
+ 'show(p)'
64
+ ]
65
+ },
66
+ 'altair': {
67
+ 'import_as': 'alt',
68
+ 'import_statement': 'import altair as alt',
69
+ 'description': 'Declarative statistical visualization (Grammar of Graphics)',
70
+ 'best_for': ['exploratory analysis', 'statistical plots', 'clean syntax'],
71
+ 'examples': [
72
+ 'chart = alt.Chart(df1).mark_circle().encode(x="column1", y="column2")',
73
+ 'chart = alt.Chart(df1).mark_bar().encode(x="category", y="count()")',
74
+ 'chart.show() # or chart.save("plot.html")'
75
+ ]
76
+ },
77
+ 'holoviews': {
78
+ 'import_as': 'hv',
79
+ 'import_statement': 'import holoviews as hv\nhv.extension("bokeh") # or "matplotlib"',
80
+ 'description': 'High-level data visualization with multiple backends',
81
+ 'best_for': ['multi-dimensional data', 'animated plots', 'complex layouts'],
82
+ 'examples': [
83
+ 'hv.Scatter(df1, "x", "y")',
84
+ 'hv.Histogram(df1["numeric_column"])',
85
+ 'hv.HeatMap(df1, ["category1", "category2"], "value")'
86
+ ]
87
+ }
88
+ }
89
+
90
+ def __init__(
91
+ self,
92
+ dataframes: Optional[Dict[str, pd.DataFrame]] = None,
93
+ df_prefix: str = "df",
94
+ generate_guide: bool = True,
95
+ include_summary_stats: bool = False,
96
+ include_sample_data: bool = False,
97
+ sample_rows: int = 3,
98
+ auto_detect_types: bool = True,
99
+ **kwargs
100
+ ):
101
+ """
102
+ Initialize the Python Pandas tool with DataFrame management.
103
+
104
+ Args:
105
+ dataframes: Dictionary of DataFrames to bind {name: DataFrame}
106
+ df_prefix: Prefix for auto-generated DataFrame aliases (default: "df")
107
+ generate_guide: Whether to generate DataFrame information guide
108
+ include_summary_stats: Include summary statistics in guide
109
+ include_sample_data: Include sample data in guide
110
+ sample_rows: Number of sample rows to show
111
+ auto_detect_types: Automatically detect and categorize column types
112
+ **kwargs: Additional arguments for PythonREPLTool
113
+ """
114
+ # Configuration
115
+ self.df_prefix = df_prefix
116
+ self.generate_guide = generate_guide
117
+ self.include_summary_stats = include_summary_stats
118
+ self.include_sample_data = include_sample_data
119
+ self.sample_rows = sample_rows
120
+ self.auto_detect_types = auto_detect_types
121
+
122
+ # DataFrame storage
123
+ self.dataframes = dataframes or {}
124
+ self.df_locals = {}
125
+ self.df_guide = ""
126
+
127
+ # Process DataFrames before initializing parent
128
+ self._process_dataframes()
129
+
130
+ # ✅ Sync df_locals to execution environment
131
+ # self.locals.update(self.df_locals)
132
+ # self.globals.update(self.df_locals)
133
+
134
+ # Set up locals with DataFrames
135
+ df_locals = kwargs.get('locals_dict', {})
136
+ df_locals.update(self.df_locals)
137
+ kwargs['locals_dict'] = df_locals
138
+
139
+ # Initialize parent class
140
+ super().__init__(**kwargs)
141
+
142
+ # Generate guide after initialization
143
+ if self.generate_guide:
144
+ self.df_guide = self._generate_dataframe_guide()
145
+
146
+ # Update description with loaded DataFrames
147
+ self._update_description()
148
+
149
+ def _update_description(self) -> None:
150
+ """Update tool description to include available DataFrames."""
151
+ df_summary = ", ".join([
152
+ f"{df_key}: {df.shape[0]} rows × {df.shape[1]} cols"
153
+ for df_key, df in self.dataframes.items()
154
+ ]) if self.dataframes else "No DataFrames"
155
+
156
+ self.description = (
157
+ f"Execute Python code with pandas DataFrames. "
158
+ f"Available data: {df_summary}. "
159
+ f"Use df1, df2, etc. to access DataFrames."
160
+ )
161
+
162
+ def _generate_plotting_guide(self) -> str:
163
+ """Generate comprehensive plotting libraries guide for the LLM."""
164
+ guide_parts = [
165
+ "# Plotting Libraries Guide",
166
+ "",
167
+ "## Available Libraries",
168
+ ""
169
+ ]
170
+
171
+ for lib_name, lib_info in self.PLOTTING_LIBRARIES.items():
172
+ guide_parts.extend([
173
+ f"### {lib_name.title()}",
174
+ f"**Import**: `{lib_info['import_statement']}`",
175
+ f"**Best for**: {', '.join(lib_info['best_for'])}",
176
+ "",
177
+ "**Examples**:",
178
+ ])
179
+ guide_parts.extend(f"- `{example}`" for example in lib_info['examples'])
180
+ guide_parts.append("")
181
+
182
+ # Add general recommendations
183
+ guide_parts.extend([
184
+ "## General Tips",
185
+ "- For static plots: Use `save_current_plot('filename.png')` with matplotlib",
186
+ "- For interactive plots: Use plotly and save as HTML",
187
+ "- For large datasets: Consider aggregation or sampling first",
188
+ "",
189
+ ])
190
+
191
+ return "\n".join(guide_parts)
192
+
193
+ def _process_dataframes(self) -> None:
194
+ """Process and bind DataFrames to the local environment.
195
+
196
+ IMPORTANT:
197
+ Original names are the PRIMARY identifiers, aliases are CONVENIENCE references.
198
+ """
199
+ self.df_locals = {}
200
+
201
+ for i, (df_name, df) in enumerate(self.dataframes.items()):
202
+ # Standardized DataFrame alias (for convenience)
203
+ df_alias = f"{self.df_prefix}{i + 1}"
204
+
205
+ # Bind DataFrame with both original name and standardized key
206
+ self.df_locals[df_name] = df # PRIMARY: Original name
207
+ self.df_locals[df_alias] = df # ALIAS: Convenience reference
208
+
209
+ for key in [df_name, df_alias]:
210
+ self.df_locals[f"{key}_row_count"] = len(df)
211
+ self.df_locals[f"{key}_col_count"] = len(df.columns)
212
+ self.df_locals[f"{key}_shape"] = df.shape
213
+ self.df_locals[f"{key}_columns"] = df.columns.tolist()
214
+ self.df_locals[f"{key}_info"] = self._get_dataframe_info(df)
215
+
216
+ def _get_dataframe_info(self, df: pd.DataFrame) -> Dict[str, Any]:
217
+ """Get comprehensive information about a DataFrame."""
218
+ info = {
219
+ 'shape': df.shape,
220
+ 'columns': df.columns.tolist(),
221
+ 'dtypes': {col: str(dtype) for col, dtype in df.dtypes.items()},
222
+ 'memory_usage_bytes': df.memory_usage(deep=True).sum(),
223
+ 'null_counts': df.isnull().sum().to_dict(),
224
+ 'row_count': len(df),
225
+ 'column_count': len(df.columns),
226
+ }
227
+
228
+ if self.auto_detect_types:
229
+ info['column_types'] = self._categorize_columns(df)
230
+
231
+ return info
232
+
233
+ def _categorize_columns(self, df: pd.DataFrame) -> Dict[str, str]:
234
+ """Categorize DataFrame columns into data types."""
235
+ column_types = {}
236
+
237
+ for col in df.columns:
238
+ if pd.api.types.is_numeric_dtype(df[col]):
239
+ if pd.api.types.is_integer_dtype(df[col]):
240
+ column_types[col] = "integer"
241
+ else:
242
+ column_types[col] = "float"
243
+ elif pd.api.types.is_datetime64_any_dtype(df[col]):
244
+ column_types[col] = "datetime"
245
+ elif pd.api.types.is_categorical_dtype(df[col]):
246
+ column_types[col] = "categorical"
247
+ elif pd.api.types.is_bool_dtype(df[col]):
248
+ column_types[col] = "boolean"
249
+ else:
250
+ # Check if it looks like categorical data
251
+ unique_ratio = df[col].nunique() / len(df) if len(df) > 0 else 0
252
+ if unique_ratio < 0.1 and df[col].nunique() < 50:
253
+ column_types[col] = "categorical_text"
254
+ else:
255
+ column_types[col] = "text"
256
+
257
+ return column_types
258
+
259
+ def _metrics_guide(self, df_key: str, df_name: str, columns: List[str]) -> str:
260
+ """Generate column information guide."""
261
+ df = self.df_locals[df_key]
262
+ column_info = []
263
+
264
+ for col in columns:
265
+ dtype = str(df[col].dtype)
266
+ category = self._categorize_columns(df)[col] if self.auto_detect_types else dtype
267
+ null_count = df[col].isnull().sum()
268
+ unique_count = df[col].nunique()
269
+
270
+ # Additional info based on data type
271
+ extra_info = []
272
+ if category in ['integer', 'float']:
273
+ min_val, max_val = df[col].min(), df[col].max()
274
+ extra_info.append(f"Range: {min_val} - {max_val}")
275
+ elif category in ['text', 'categorical_text']:
276
+ extra_info.append(f"Unique values: {unique_count}")
277
+ if unique_count <= 10:
278
+ unique_vals = df[col].unique()[:5]
279
+ extra_info.append(f"Sample values: {list(unique_vals)}")
280
+
281
+ extra_str = f" ({', '.join(extra_info)})" if extra_info else ""
282
+ null_str = f" [Nulls: {null_count}]" if null_count > 0 else ""
283
+
284
+ column_info.append(f"- **{col}**: {dtype} → {category}{extra_str}{null_str}")
285
+
286
+ return "\n".join(column_info)
287
+
288
+ def _generate_dataframe_guide(self) -> str:
289
+ """Generate comprehensive DataFrame guide for the LLM."""
290
+ if not self.dataframes:
291
+ return "No DataFrames loaded."
292
+
293
+ guide_parts = [
294
+ "# DataFrame Guide",
295
+ "",
296
+ f"**Total DataFrames**: {len(self.dataframes)}",
297
+ "",
298
+ "## Available DataFrames:",
299
+ ]
300
+
301
+ for i, (df_name, df) in enumerate(self.dataframes.items()):
302
+ df_alias = f"{self.df_prefix}{i + 1}"
303
+ shape = df.shape
304
+
305
+ guide_parts.extend([
306
+ f"### DataFrame: `{df_name}` (alias: `{df_alias}`)",
307
+ f"- **Primary Name**: `{df_name}` ← Use this in your code",
308
+ f"- **Alias**: `{df_alias}` (convenience reference)",
309
+ f"- **Shape**: {shape[0]:,} rows × {shape[1]} columns",
310
+ f"- **Columns**: {', '.join(df.columns.tolist()[:10])}{'...' if len(df.columns) > 10 else ''}",
311
+ ""
312
+ ])
313
+ # self._metrics_guide(df_key, df_name, df.columns.tolist()),
314
+
315
+ # Add summary statistics for numeric columns
316
+ if self.include_summary_stats:
317
+ numeric_cols = df.select_dtypes(include=[np.number]).columns
318
+ if len(numeric_cols) > 0:
319
+ guide_parts.append("- **Numeric Summary**:")
320
+ guide_parts.extend(
321
+ f" - `{col}`: min={df[col].min():.2f}, max={df[col].max():.2f}, mean={df[col].mean():.2f}"
322
+ for col in numeric_cols[:5]
323
+ )
324
+ guide_parts.append("")
325
+
326
+ # Null value summary
327
+ null_counts = df.isnull().sum()
328
+ if null_counts.sum() > 0:
329
+ null_summary = [f"`{col}`: {count}" for col, count in null_counts.items() if count > 0]
330
+ guide_parts.extend([
331
+ "- **Missing Values**:",
332
+ f" {', '.join(null_summary)}",
333
+ ""
334
+ ])
335
+
336
+ # Usage examples
337
+ guide_parts.extend([
338
+ "## Usage Examples",
339
+ "",
340
+ "**IMPORTANT**: Always use the PRIMARY dataframe names in your code:",
341
+ "",
342
+ "```python",
343
+ ])
344
+
345
+ # Add real examples using actual dataframe names
346
+ if self.dataframes:
347
+ first_name = list(self.dataframes.keys())[0]
348
+ first_alias = f"{self.df_prefix}1"
349
+ guide_parts.extend([
350
+ f"# ✅ CORRECT: Use original names",
351
+ f"print({first_name}.shape) # Access by original name",
352
+ f"result = {first_name}.groupby('column_name').size()",
353
+ f"filtered = {first_name}[{first_name}['column'] > 100]",
354
+ "",
355
+ f"# ✅ ALSO WORKS: Use aliases if more convenient",
356
+ f"print({first_alias}.shape) # Same DataFrame, different name",
357
+ "",
358
+ "# Store results for later use",
359
+ "execution_results['my_analysis'] = result",
360
+ "",
361
+ "# Create visualizations",
362
+ "import matplotlib.pyplot as plt",
363
+ "plt.figure(figsize=(10, 6))",
364
+ f"plt.hist({first_name}['numeric_column'])",
365
+ "plt.title('Distribution')",
366
+ "save_current_plot('histogram.png')",
367
+ ])
368
+
369
+ guide_parts.extend([
370
+ "```",
371
+ "",
372
+ "## Key Points",
373
+ "",
374
+ "1. **Primary Names**: Use the original DataFrame names (e.g., `epson_sales_brian_bi`)",
375
+ f"2. **Aliases Available**: You can also use `{self.df_prefix}1`, `{self.df_prefix}2`, etc. if shorter names are preferred",
376
+ "3. **Both Work**: The DataFrames are accessible by BOTH names in the execution environment",
377
+ "4. **Recommendation**: Use original names for clarity, aliases for brevity",
378
+ ""
379
+ ])
380
+
381
+ return "\n".join(guide_parts)
382
+
383
+ def add_dataframe(self, name: str, df: pd.DataFrame, regenerate_guide: bool = True) -> str:
384
+ """
385
+ Add a new DataFrame to the tool.
386
+
387
+ Args:
388
+ name: Name for the DataFrame
389
+ df: The DataFrame to add
390
+ regenerate_guide: Whether to regenerate the guide
391
+
392
+ Returns:
393
+ Success message with DataFrame key
394
+ """
395
+ if not isinstance(df, pd.DataFrame):
396
+ raise ValueError("Object must be a pandas DataFrame")
397
+
398
+ # Add to dataframes dict
399
+ self.dataframes[name] = df
400
+
401
+ # Reprocess all DataFrames
402
+ self._process_dataframes()
403
+
404
+ # Update locals in the execution environment
405
+ self.locals.update(self.df_locals)
406
+ self.globals.update(self.df_locals)
407
+
408
+ # Regenerate guide if requested
409
+ if regenerate_guide and self.generate_guide:
410
+ self.df_guide = self._generate_dataframe_guide()
411
+
412
+ # Find the standardized key for this DataFrame
413
+ df_alias = next(
414
+ (
415
+ f"{self.df_prefix}{i + 1}"
416
+ for i, (df_name, _) in enumerate(self.dataframes.items())
417
+ if df_name == name
418
+ ),
419
+ None,
420
+ )
421
+
422
+ # Update description
423
+ self._update_description()
424
+
425
+ return f"DataFrame '{name}' added successfully (alias: '{df_alias}')"
426
+
427
+ def remove_dataframe(self, name: str, regenerate_guide: bool = True) -> str:
428
+ """
429
+ Remove a DataFrame from the tool.
430
+
431
+ Args:
432
+ name: Name of the DataFrame to remove
433
+ regenerate_guide: Whether to regenerate the guide
434
+
435
+ Returns:
436
+ Success message
437
+ """
438
+ # Resolve alias to original name if needed
439
+ resolved_name = next(
440
+ (
441
+ df_name
442
+ for i, (df_name, _) in enumerate(self.dataframes.items())
443
+ if f"{self.df_prefix}{i + 1}" == name
444
+ ),
445
+ name,
446
+ )
447
+
448
+ if resolved_name not in self.dataframes:
449
+ raise ValueError(f"DataFrame '{name}' not found")
450
+
451
+ # Remove from dataframes dict
452
+ del self.dataframes[resolved_name]
453
+
454
+ # Reprocess DataFrames
455
+ self._process_dataframes()
456
+
457
+ # Update execution environment
458
+ self.locals.update(self.df_locals)
459
+ self.globals.update(self.df_locals)
460
+
461
+ # Regenerate guide if requested
462
+ if regenerate_guide and self.generate_guide:
463
+ self.df_guide = self._generate_dataframe_guide()
464
+
465
+ # Update description
466
+ self._update_description()
467
+
468
+ return f"DataFrame '{resolved_name}' removed successfully"
469
+
470
+ def get_dataframe_guide(self) -> str:
471
+ """Get the current DataFrame guide."""
472
+ return self.df_guide
473
+
474
+ def list_dataframes(self) -> Dict[str, Dict[str, Any]]:
475
+ """
476
+ List all available DataFrames with their info.
477
+
478
+ Returns original names as keys with alias info included.
479
+ """
480
+ result = {}
481
+ for i, (df_name, df) in enumerate(self.dataframes.items()):
482
+ df_alias = f"{self.df_prefix}{i + 1}"
483
+ result[df_name] = { # KEY CHANGE: Use original name as key
484
+ 'original_name': df_name,
485
+ 'alias': df_alias,
486
+ 'shape': df.shape,
487
+ 'columns': df.columns.tolist(),
488
+ 'memory_usage_mb': df.memory_usage(deep=True).sum() / 1024 / 1024,
489
+ 'null_count': df.isnull().sum().sum(),
490
+ }
491
+ return result
492
+
493
+ def get_dataframe_summary(self, df_key: str) -> Dict[str, Any]:
494
+ """Get detailed summary for a specific DataFrame (accepts both original name and alias)."""
495
+ if df_key not in self.df_locals:
496
+ available = list(self.dataframes.keys())
497
+ raise ValueError(f"DataFrame '{df_key}' not found. Available: {available}")
498
+
499
+ df = self.df_locals[df_key]
500
+ return self._get_dataframe_info(df)
501
+
502
+ def _setup_environment(self) -> None:
503
+ """Override to add DataFrame-specific utilities."""
504
+ # Call parent setup first
505
+ super()._setup_environment()
506
+
507
+ # Add DataFrame-specific utilities
508
+ def list_available_dataframes():
509
+ """List all available DataFrames."""
510
+ return self.list_dataframes()
511
+
512
+ def get_df_guide():
513
+ """Get the DataFrame guide."""
514
+ return self.get_dataframe_guide()
515
+
516
+ def get_plotting_guide():
517
+ """Get the plotting libraries guide."""
518
+ return self._generate_plotting_guide()
519
+
520
+ def quick_eda(df_key: str):
521
+ """Quick exploratory data analysis for a DataFrame."""
522
+ if df_key not in self.df_locals:
523
+ return f"DataFrame '{df_key}' not found. Available: {list(self.dataframes.keys())}"
524
+
525
+ df = self.df_locals[df_key]
526
+
527
+ print(f"=== Quick EDA for {df_key} ===")
528
+ print(f"Shape: {df.shape}")
529
+ print(f"Columns: {df.columns.tolist()}")
530
+ print(f"\nData Types:")
531
+ print(df.dtypes)
532
+ print(f"\nMissing Values:")
533
+ print(df.isnull().sum())
534
+ print(f"\nSample Data:")
535
+ print(df.head())
536
+
537
+ return f"EDA completed for {df_key}"
538
+
539
+ # Add to locals
540
+ self.locals.update({
541
+ 'list_available_dataframes': list_available_dataframes,
542
+ 'get_df_guide': get_df_guide,
543
+ 'quick_eda': quick_eda,
544
+ 'get_plotting_guide': get_plotting_guide,
545
+ })
546
+
547
+ # Update globals
548
+ self.globals.update(self.locals)
549
+
550
+ def _get_default_setup_code(self) -> str:
551
+ """Override to include DataFrame-specific setup."""
552
+ base_setup = super()._get_default_setup_code()
553
+
554
+ # Generate the DataFrame info statically since we know the DataFrames at this point
555
+ df_count = len(self.dataframes)
556
+ df_info_lines = []
557
+
558
+ if df_count > 0:
559
+ df_info_lines.append("print('📊 Available DataFrames:')")
560
+ for i, (name, df) in enumerate(self.dataframes.items()):
561
+ df_alias = f"{self.df_prefix}{i + 1}"
562
+ shape = df.shape
563
+ df_info_lines.append(
564
+ f"print(' - {name} (alias: {df_alias}): "
565
+ f"{shape[0]} rows × {shape[1]} columns')"
566
+ )
567
+
568
+ df_info_code = '\n'.join(df_info_lines)
569
+
570
+ df_setup = f"""
571
+ # DataFrame-specific setup
572
+ print("📊 DataFrames loaded: {df_count}")
573
+ {df_info_code}
574
+ print("💡 TIP: Use original names (e.g., 'bi_sales') or aliases (e.g., 'df1')")
575
+ print("🔧 Utilities: list_available_dataframes(), get_df_guide(), quick_eda()")
576
+ """
577
+
578
+ return base_setup + df_setup
579
+
580
+ def get_environment_info(self) -> Dict[str, Any]:
581
+ """Override to include DataFrame information."""
582
+ info = super().get_environment_info()
583
+ info.update({
584
+ 'dataframes_count': len(self.dataframes),
585
+ 'dataframes': self.list_dataframes(),
586
+ 'df_prefix': self.df_prefix,
587
+ 'guide_generated': bool(self.df_guide),
588
+ })
589
+ return info
590
+
591
+ def get_execution_state(self) -> Dict[str, Any]:
592
+ """
593
+ Extract current execution state for use by formatters.
594
+
595
+ Returns:
596
+ Dictionary containing:
597
+ - execution_results: All stored results
598
+ - dataframes: Dict of available DataFrames
599
+ - variables: Other variables from execution
600
+ """
601
+ state = {
602
+ 'execution_results': self.locals.get('execution_results', {}),
603
+ 'dataframes': {},
604
+ 'variables': {}
605
+ }
606
+
607
+ # Extract DataFrames
608
+ for name, df in self.dataframes.items():
609
+ state['dataframes'][name] = df
610
+ # Also include by alias
611
+ for i, (df_name, _) in enumerate(self.dataframes.items()):
612
+ if df_name == name:
613
+ alias = f"{self.df_prefix}{i + 1}"
614
+ state['dataframes'][alias] = df
615
+ break
616
+
617
+ # Extract other relevant variables (excluding functions, modules)
618
+ for key, value in self.locals.items():
619
+ if not key.startswith('_') and not callable(value) and (key not in ['execution_results'] and not key.endswith('_row_count')):
620
+ with contextlib.suppress(Exception):
621
+ # Only include serializable or DataFrame-like objects
622
+ if isinstance(value, (str, int, float, bool, list, dict, pd.DataFrame, pd.Series)):
623
+ state['variables'][key] = value
624
+
625
+ return state
626
+
627
+ def clear_execution_results(self):
628
+ """Clear execution_results dictionary for new queries."""
629
+ if 'execution_results' in self.locals:
630
+ self.locals['execution_results'].clear()