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,341 @@
1
+ from typing import Any, Optional, Tuple, Dict, List
2
+ import json
3
+ import uuid
4
+ from pathlib import Path
5
+ from .chart import BaseChart
6
+ from . import register_renderer
7
+ from ...models.outputs import OutputMode
8
+
9
+ try:
10
+ from rich.panel import Panel
11
+ from rich.syntax import Syntax
12
+ RICH_AVAILABLE = True
13
+ except ImportError:
14
+ RICH_AVAILABLE = False
15
+
16
+ try:
17
+ from ipywidgets import HTML as IPyHTML
18
+ IPYWIDGETS_AVAILABLE = True
19
+ except ImportError:
20
+ IPYWIDGETS_AVAILABLE = False
21
+
22
+
23
+ PLOTLY_SYSTEM_PROMPT = """PLOTLY CHART OUTPUT MODE:
24
+ Generate an interactive chart using Plotly.
25
+
26
+ REQUIREMENTS:
27
+ 1. Return Python code in a markdown code block (```python)
28
+ 2. Use plotly.graph_objects or plotly.express
29
+ 3. Store the figure in a variable named 'fig', 'chart', or 'plot'
30
+ 4. Make the chart self-contained with inline data
31
+ 5. Use appropriate chart types (scatter, bar, line, pie, etc.)
32
+ 6. Add titles, labels, and legends for clarity
33
+ 7. Configure layout for better visualization
34
+ 8. DO NOT execute the code or save files - return code only
35
+
36
+ EXAMPLE:
37
+ ```python
38
+ import plotly.graph_objects as go
39
+
40
+ fig = go.Figure(data=[
41
+ go.Bar(
42
+ x=['Product A', 'Product B', 'Product C', 'Product D'],
43
+ y=[20, 14, 23, 25],
44
+ marker_color='indianred'
45
+ )
46
+ ])
47
+
48
+ fig.update_layout(
49
+ title='Sales by Product',
50
+ xaxis_title='Product',
51
+ yaxis_title='Sales',
52
+ template='plotly_white'
53
+ )
54
+ ```
55
+ """
56
+
57
+
58
+ @register_renderer(OutputMode.PLOTLY, system_prompt=PLOTLY_SYSTEM_PROMPT)
59
+ class PlotlyRenderer(BaseChart):
60
+ """Renderer for Plotly charts"""
61
+
62
+ def execute_code(
63
+ self,
64
+ code: str,
65
+ pandas_tool: Any = None,
66
+ execution_state: Optional[Dict[str, Any]] = None,
67
+ **kwargs,
68
+ ) -> Tuple[Any, Optional[str]]:
69
+ """Execute Plotly code within the shared Python environment."""
70
+
71
+ # Execute using BaseRenderer logic
72
+ context, error = super().execute_code(
73
+ code,
74
+ pandas_tool=pandas_tool,
75
+ execution_state=execution_state,
76
+ **kwargs,
77
+ )
78
+
79
+ if error:
80
+ return None, error
81
+
82
+ if not context:
83
+ return None, "Execution context was empty"
84
+
85
+ # Find the figure objects
86
+ if figures := self._find_chart_objects(context):
87
+ return figures, None
88
+
89
+ return None, "Code must define a figure variable (fig, chart, plot)"
90
+
91
+ @staticmethod
92
+ def _find_chart_objects(context: Dict[str, Any]) -> List[Any]:
93
+ """Locate all figure objects in the local namespace."""
94
+ figures: List[Any] = []
95
+ seen_ids = set()
96
+
97
+ def add_fig(obj: Any) -> None:
98
+ if obj is None:
99
+ return
100
+
101
+ # Skip renderer / BaseChart instances (like `self`)
102
+ if isinstance(obj, BaseChart):
103
+ return
104
+
105
+ # Heuristic: Plotly figures usually have `to_json`, `to_dict`, and `data`
106
+ looks_like_plotly_figure = (
107
+ hasattr(obj, "to_json")
108
+ and hasattr(obj, "to_dict")
109
+ and hasattr(obj, "data")
110
+ )
111
+
112
+ # Also allow dict-like Plotly specs (e.g. already serialized)
113
+ looks_like_figure_dict = isinstance(obj, dict) and "data" in obj
114
+
115
+ if (looks_like_plotly_figure or looks_like_figure_dict) and id(obj) not in seen_ids:
116
+ figures.append(obj)
117
+ seen_ids.add(id(obj))
118
+
119
+ # 1. Priority search for common variable names to preserve order
120
+ priority_vars = ['fig', 'figure', 'chart', 'plot']
121
+ for var_name in priority_vars:
122
+ if var_name in context:
123
+ add_fig(context[var_name])
124
+
125
+ # 2. Scan all locals for other figure objects
126
+ for var_name, obj in context.items():
127
+ if var_name.startswith('_') or var_name in priority_vars:
128
+ continue
129
+ add_fig(obj)
130
+
131
+ return figures
132
+
133
+ def _render_chart_content(self, chart_objs: Any, **kwargs) -> str:
134
+ """
135
+ Render Plotly-specific chart content (HTML/JS).
136
+ Handles a single figure or a list of figures.
137
+ """
138
+ # Ensure we have a list
139
+ figures = chart_objs if isinstance(chart_objs, list) else [chart_objs]
140
+
141
+ html_parts = []
142
+
143
+ # Config options (can be passed via kwargs)
144
+ config = kwargs.get('config', {
145
+ 'displayModeBar': True,
146
+ 'responsive': True,
147
+ 'displaylogo': False
148
+ })
149
+ config_json = json.dumps(config)
150
+
151
+ for i, chart_obj in enumerate(figures):
152
+ chart_id = f"plotly-chart-{uuid.uuid4().hex[:8]}"
153
+
154
+ # Convert figure to JSON
155
+ try:
156
+ if hasattr(chart_obj, "to_json") and callable(chart_obj.to_json):
157
+ fig_json = chart_obj.to_json()
158
+ else:
159
+ raise AttributeError
160
+ except (AttributeError, TypeError):
161
+ # Fallback if it's a dict or other format
162
+ fig_json = json.dumps(chart_obj, default=str)
163
+
164
+ # Generate HTML/JS for this specific chart
165
+ chart_html = f'''
166
+ <div class="plotly-chart-wrapper" style="margin-bottom: 20px;">
167
+ <div id="{chart_id}" style="width: 100%; height: 100%; min-height: 450px;"></div>
168
+ <script type="text/javascript">
169
+ (function() {{
170
+ var figure = {fig_json};
171
+ var config = {config_json};
172
+
173
+ if (typeof Plotly === 'undefined') {{
174
+ console.error("Plotly library not loaded");
175
+ document.getElementById('{chart_id}').innerHTML = "Error: Plotly library not loaded.";
176
+ return;
177
+ }}
178
+
179
+ Plotly.newPlot('{chart_id}', figure.data, figure.layout, config)
180
+ .then(function() {{
181
+ console.log('Plotly chart {chart_id} rendered successfully');
182
+ }})
183
+ .catch(function(error) {{
184
+ console.error('Error rendering Plotly chart:', error);
185
+ document.getElementById('{chart_id}').innerHTML =
186
+ '<div style="color:red; padding:10px;">⚠️ Chart Rendering Error: ' + error.message + '</div>';
187
+ }});
188
+ }})();
189
+ </script>
190
+ </div>
191
+ '''
192
+ html_parts.append(chart_html)
193
+
194
+ return "\n".join(html_parts)
195
+
196
+ def _save_to_disk(self, chart_objs: Any, filename: str = None) -> str:
197
+ """Save chart(s) to HTML file for terminal viewing."""
198
+ if not filename:
199
+ filename = f"plotly_{uuid.uuid4().hex[:8]}.html"
200
+
201
+ output_dir = Path("outputs/charts")
202
+ output_dir.mkdir(parents=True, exist_ok=True)
203
+
204
+ filepath = output_dir / filename
205
+
206
+ # Handle list or single object
207
+ figures = chart_objs if isinstance(chart_objs, list) else [chart_objs]
208
+
209
+ # Create a combined HTML file
210
+ with open(filepath, 'w', encoding='utf-8') as f:
211
+ f.write('<html><head><script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script></head><body>')
212
+ for fig in figures:
213
+ if hasattr(fig, 'to_html'):
214
+ # Get inner HTML div
215
+ div = fig.to_html(include_plotlyjs=False, full_html=False)
216
+ f.write(f'<div style="margin-bottom: 30px;">{div}</div>')
217
+ else:
218
+ f.write(f'<div>Unable to render object of type {type(fig)}</div>')
219
+ f.write('</body></html>')
220
+
221
+ return str(filepath)
222
+
223
+ def to_html(
224
+ self,
225
+ chart_obj: Any,
226
+ mode: str = 'partial',
227
+ **kwargs
228
+ ) -> str:
229
+ """
230
+ Convert Plotly chart(s) to HTML.
231
+ """
232
+ # Plotly library for <head>
233
+ extra_head = '''
234
+ <!-- Plotly.js -->
235
+ <script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
236
+ '''
237
+
238
+ kwargs['extra_head'] = kwargs.get('extra_head', extra_head)
239
+
240
+ # Call parent to_html (which calls _render_chart_content)
241
+ return super().to_html(chart_obj, mode=mode, **kwargs)
242
+
243
+ def to_json(self, chart_obj: Any) -> Optional[Any]:
244
+ """Export Plotly JSON specification (returns list if multiple)."""
245
+ figures = chart_obj if isinstance(chart_obj, list) else [chart_obj]
246
+ results = []
247
+
248
+ for fig in figures:
249
+ try:
250
+ if hasattr(fig, 'to_json'):
251
+ results.append(json.loads(fig.to_json()))
252
+ else:
253
+ results.append(fig) # It might already be a dict
254
+ except Exception as e:
255
+ results.append({'error': str(e)})
256
+
257
+ return results if len(results) > 1 else results[0] if results else None
258
+
259
+ async def render(
260
+ self,
261
+ response: Any,
262
+ theme: str = 'monokai',
263
+ environment: str = 'html',
264
+ include_code: bool = False,
265
+ html_mode: str = 'partial',
266
+ **kwargs
267
+ ) -> Tuple[Any, Optional[Any]]:
268
+ """Render Plotly chart."""
269
+
270
+ # 1. Extract Code
271
+ code = getattr(response, 'code', None)
272
+ output_format = kwargs.get('output_format', environment)
273
+
274
+ # Fallback to extracting from text content
275
+ if not code:
276
+ content = self._get_content(response)
277
+ code = self._extract_code(content)
278
+
279
+ if not code:
280
+ error_msg = "No chart code found in response"
281
+ if output_format == 'terminal':
282
+ return error_msg, None
283
+ return self._wrap_for_environment(
284
+ f"<div class='error'>{error_msg}</div>",
285
+ output_format
286
+ ), None
287
+
288
+ # 2. Execute Code
289
+ chart_objs, error = self.execute_code(
290
+ code,
291
+ pandas_tool=kwargs.pop('pandas_tool', None),
292
+ execution_state=kwargs.pop('execution_state', None),
293
+ **kwargs,
294
+ )
295
+
296
+ if error:
297
+ if output_format == 'terminal':
298
+ return f"Error generating chart: {error}", None
299
+ return self._wrap_for_environment(
300
+ self._render_error(error, code, theme),
301
+ output_format
302
+ ), None
303
+
304
+ # 3. Handle Terminal Environment (Save to Disk)
305
+ if output_format == 'terminal':
306
+ try:
307
+ saved_path = self._save_to_disk(chart_objs)
308
+ msg = f"Interactive chart saved to: {saved_path}"
309
+ if RICH_AVAILABLE:
310
+ return Panel(msg, title="📊 Plotly Chart", border_style="blue"), None
311
+ return msg, None
312
+ except Exception as e:
313
+ return f"Chart generated but failed to save: {e}", None
314
+
315
+ # 4. Generate HTML for Web/Jupyter
316
+ html_output = self.to_html(
317
+ chart_objs,
318
+ mode=html_mode,
319
+ include_code=include_code,
320
+ code=code,
321
+ theme=theme,
322
+ title=kwargs.get('title', 'Plotly Chart'),
323
+ icon='📊',
324
+ **kwargs
325
+ )
326
+
327
+ # 5. Wrap for Environment
328
+ if output_format in {'jupyter', 'notebook', 'ipython', 'colab'}:
329
+ # For Jupyter, we generally want the widget if possible, but pure HTML also works
330
+ if IPYWIDGETS_AVAILABLE:
331
+ return code, IPyHTML(value=html_output)
332
+ return code, html_output
333
+
334
+ # 6. Return based on output format
335
+ if output_format == 'html':
336
+ return code, html_output
337
+ elif output_format == 'json':
338
+ return code, self.to_json(chart_objs)
339
+
340
+ # Default behavior: Return code as content, HTML as wrapped
341
+ return code, html_output
@@ -0,0 +1,310 @@
1
+ from typing import Any, Optional, Tuple, Dict, List
2
+ import contextlib
3
+ import io
4
+ import base64
5
+ import uuid
6
+ from .chart import BaseChart
7
+ from . import register_renderer
8
+ from ...models.outputs import OutputMode
9
+
10
+
11
+ SEABORN_SYSTEM_PROMPT = """SEABORN CHART OUTPUT MODE:
12
+ Generate polished statistical visualizations using Seaborn.
13
+
14
+ REQUIREMENTS:
15
+ 1. Return Python code in a markdown code block (```python)
16
+ 2. Import seaborn as sns and set a theme with sns.set_theme()
17
+ 3. Load or create data directly in the example (use sns.load_dataset or inline data)
18
+ 4. Store the figure in 'fig' (sns.relplot returns a FacetGrid; use .fig) or fall back to plt.gcf()
19
+ 5. Add descriptive titles, axis labels, and legend/annotation cues
20
+ 6. Prefer seaborn high-level functions (relplot, catplot, histplot, heatmap, etc.)
21
+ 7. Keep charts self-contained—no external files or plt.show()
22
+
23
+ EXAMPLE:
24
+ ```python
25
+ # Import seaborn
26
+ import seaborn as sns
27
+
28
+ # Apply the default theme
29
+ sns.set_theme()
30
+
31
+ # Load an example dataset
32
+ tips = sns.load_dataset("tips")
33
+
34
+ # Create a visualization
35
+ sns.relplot(
36
+ data=tips,
37
+ x="total_bill", y="tip", col="time",
38
+ hue="smoker", style="smoker", size="size",
39
+ )
40
+ ```
41
+
42
+ Explanation:
43
+ - sns.set_theme() ensures a consistent, modern aesthetic.
44
+ - Inline dataset loading keeps the code runnable anywhere.
45
+ - relplot showcases multi-faceted Seaborn features (faceting, hue, style, size).
46
+ - Returning only the code snippet allows the renderer to execute it safely.
47
+ """
48
+
49
+
50
+ @register_renderer(OutputMode.SEABORN, system_prompt=SEABORN_SYSTEM_PROMPT)
51
+ class SeabornRenderer(BaseChart):
52
+ """Renderer for Seaborn charts (rendered as static images)."""
53
+
54
+ def execute_code(
55
+ self,
56
+ code: str,
57
+ pandas_tool: Any = None,
58
+ execution_state: Optional[Dict[str, Any]] = None,
59
+ **kwargs,
60
+ ) -> Tuple[Any, Optional[str]]:
61
+ """Execute Seaborn code and return all underlying Matplotlib figures."""
62
+ manual_backend = pandas_tool is None
63
+ extra_namespace = None
64
+
65
+ if manual_backend:
66
+ import matplotlib
67
+ matplotlib.use('Agg')
68
+ import matplotlib.pyplot as plt
69
+ import seaborn as sns
70
+ extra_namespace = {
71
+ 'sns': sns,
72
+ 'plt': plt,
73
+ 'matplotlib': matplotlib,
74
+ }
75
+
76
+ try:
77
+ # Execute using BaseRenderer logic
78
+ context, error = super().execute_code(
79
+ code,
80
+ pandas_tool=pandas_tool,
81
+ execution_state=execution_state,
82
+ extra_namespace=extra_namespace,
83
+ **kwargs,
84
+ )
85
+
86
+ if error:
87
+ return None, error
88
+
89
+ if not context:
90
+ return None, "Execution context was empty"
91
+
92
+ # Find all figure objects
93
+ figures = self._find_chart_objects(context)
94
+
95
+ if figures:
96
+ return figures, None
97
+
98
+ return None, "Code must define a figure variable (fig, chart, plot) or create matplotlib figures"
99
+
100
+ finally:
101
+ if manual_backend:
102
+ with contextlib.suppress(Exception):
103
+ import matplotlib.pyplot as plt
104
+ plt.close('all')
105
+
106
+ @staticmethod
107
+ def _find_chart_objects(context: Dict[str, Any]) -> List[Any]:
108
+ """Locate all matplotlib figure objects in the local namespace."""
109
+ figures: List[Any] = []
110
+ seen_ids = set()
111
+
112
+ def add_fig(obj: Any) -> None:
113
+ if obj is None:
114
+ return
115
+
116
+ # Skip renderer / BaseChart instances (like `self`)
117
+ if isinstance(obj, BaseChart):
118
+ return
119
+
120
+ # Check if it's a matplotlib Figure
121
+ has_savefig = hasattr(obj, 'savefig')
122
+ has_axes = hasattr(obj, 'axes')
123
+
124
+ # Check if it's a Seaborn FacetGrid or similar
125
+ has_fig_attr = hasattr(obj, 'fig') and hasattr(obj.fig, 'savefig')
126
+
127
+ # Check if it's a matplotlib Axes
128
+ is_axes = hasattr(obj, 'figure') and hasattr(obj.figure, 'savefig')
129
+
130
+ if has_fig_attr:
131
+ # Handle FacetGrid, PairGrid, etc.
132
+ fig = obj.fig
133
+ if id(fig) not in seen_ids:
134
+ figures.append(fig)
135
+ seen_ids.add(id(fig))
136
+ elif is_axes:
137
+ # Handle Axes objects
138
+ fig = obj.figure
139
+ if id(fig) not in seen_ids:
140
+ figures.append(fig)
141
+ seen_ids.add(id(fig))
142
+ elif has_savefig and has_axes and id(obj) not in seen_ids:
143
+ # Handle Figure objects directly
144
+ figures.append(obj)
145
+ seen_ids.add(id(obj))
146
+
147
+ # 1. Priority search for common variable names to preserve order
148
+ priority_vars = ['fig', 'figure', 'chart', 'plot', 'g', 'grid', 'ax', 'axes']
149
+ for var_name in priority_vars:
150
+ if var_name in context:
151
+ add_fig(context[var_name])
152
+
153
+ # 2. Scan all locals for other figure objects
154
+ for var_name, obj in context.items():
155
+ if var_name.startswith('_') or var_name in priority_vars:
156
+ continue
157
+ add_fig(obj)
158
+
159
+ # 3. Fallback: try to get current figure from plt if available
160
+ if not figures and 'plt' in context:
161
+ try:
162
+ fig = context['plt'].gcf()
163
+ if fig and hasattr(fig, 'savefig') and id(fig) not in seen_ids:
164
+ figures.append(fig)
165
+ except Exception:
166
+ pass
167
+
168
+ return figures
169
+
170
+ def _render_chart_content(self, chart_objs: Any, **kwargs) -> str:
171
+ """
172
+ Render Seaborn chart(s) as embedded base64 image(s).
173
+ Handles a single figure or a list of figures.
174
+ """
175
+ # Ensure we have a list
176
+ figures = chart_objs if isinstance(chart_objs, list) else [chart_objs]
177
+
178
+ html_parts = []
179
+ img_format = kwargs.get('format', 'png')
180
+ dpi = kwargs.get('dpi', 110)
181
+
182
+ for i, chart_obj in enumerate(figures):
183
+ img_id = f"seaborn-chart-{uuid.uuid4().hex[:8]}"
184
+
185
+ # Render figure to base64
186
+ buffer = io.BytesIO()
187
+ chart_obj.savefig(buffer, format=img_format, dpi=dpi, bbox_inches='tight')
188
+ buffer.seek(0)
189
+ img_base64 = base64.b64encode(buffer.read()).decode('utf-8')
190
+ buffer.close()
191
+
192
+ chart_html = f'''
193
+ <div class="seaborn-chart-wrapper" style="margin-bottom: 20px; width: 100%;">
194
+ <img id="{img_id}"
195
+ src="data:image/{img_format};base64,{img_base64}"
196
+ style="width: 100%; height: auto; display: block; margin: 0 auto;"
197
+ alt="Seaborn Chart {i+1}" />
198
+ </div>
199
+ '''
200
+ html_parts.append(chart_html)
201
+
202
+ return "\n".join(html_parts)
203
+
204
+ def to_html(
205
+ self,
206
+ chart_obj: Any,
207
+ mode: str = 'partial',
208
+ **kwargs
209
+ ) -> str:
210
+ """Convert Seaborn chart(s) to HTML."""
211
+ kwargs['extra_head'] = kwargs.get('extra_head', '')
212
+
213
+ # Call parent to_html (which calls _render_chart_content)
214
+ return super().to_html(chart_obj, mode=mode, **kwargs)
215
+
216
+ def to_json(self, chart_obj: Any) -> Optional[Any]:
217
+ """Return metadata noting Seaborn renders as static images."""
218
+ figures = chart_obj if isinstance(chart_obj, list) else [chart_obj]
219
+
220
+ results = []
221
+ for fig in figures:
222
+ results.append({
223
+ 'type': 'seaborn',
224
+ 'note': 'Seaborn visualizations render as Matplotlib figures encoded into base64 images.',
225
+ 'figure_size': list(fig.get_size_inches()) if hasattr(fig, 'get_size_inches') else None,
226
+ 'dpi': fig.dpi if hasattr(fig, 'dpi') else None,
227
+ })
228
+
229
+ return results if len(results) > 1 else results[0] if results else None
230
+
231
+ async def render(
232
+ self,
233
+ response: Any,
234
+ theme: str = 'monokai',
235
+ environment: str = 'html',
236
+ include_code: bool = False,
237
+ html_mode: str = 'partial',
238
+ **kwargs
239
+ ) -> Tuple[Any, Optional[Any]]:
240
+ """Render Seaborn chart(s)."""
241
+
242
+ # 1. Extract Code
243
+ code = getattr(response, 'code', None)
244
+ output_format = kwargs.get('output_format', environment)
245
+
246
+ # Fallback to extracting from text content
247
+ if not code:
248
+ content = self._get_content(response)
249
+ code = self._extract_code(content)
250
+
251
+ if not code:
252
+ error_msg = "No chart code found in response"
253
+ if output_format == 'terminal':
254
+ return error_msg, None
255
+ return self._wrap_for_environment(
256
+ f"<div class='error'>{error_msg}</div>",
257
+ output_format
258
+ ), None
259
+
260
+ # 2. Execute Code
261
+ chart_objs, error = self.execute_code(
262
+ code,
263
+ pandas_tool=kwargs.pop('pandas_tool', None),
264
+ execution_state=kwargs.pop('execution_state', None),
265
+ **kwargs,
266
+ )
267
+
268
+ if error:
269
+ if output_format == 'terminal':
270
+ return f"Error generating chart: {error}", None
271
+ return self._wrap_for_environment(
272
+ self._render_error(error, code, theme),
273
+ output_format
274
+ ), None
275
+
276
+ # 3. Handle Jupyter/Notebook Environment
277
+ if output_format in {'jupyter', 'notebook', 'ipython', 'colab'}:
278
+ # For Jupyter, return the figure object(s) directly
279
+ # The frontend will handle rendering them
280
+ if isinstance(chart_objs, list):
281
+ # If multiple figures, return them as a tuple
282
+ return code, chart_objs if len(chart_objs) > 1 else chart_objs[0]
283
+ return code, chart_objs
284
+
285
+ # 4. Generate HTML for Web/Terminal
286
+ html_output = self.to_html(
287
+ chart_objs,
288
+ mode=html_mode,
289
+ include_code=include_code,
290
+ code=code,
291
+ theme=theme,
292
+ title=kwargs.get('title', 'Seaborn Chart'),
293
+ icon='🎨',
294
+ dpi=kwargs.get('dpi', 110),
295
+ format=kwargs.get('img_format', 'png'),
296
+ **kwargs
297
+ )
298
+
299
+ # 5. Return based on output format
300
+ if output_format == 'html':
301
+ return code, html_output
302
+ elif output_format == 'json':
303
+ return code, self.to_json(chart_objs)
304
+ elif output_format == 'terminal':
305
+ # For terminal, could save to file like Plotly does
306
+ # For now, return the HTML
307
+ return code, html_output
308
+
309
+ # Default behavior: Return code as content, HTML as wrapped
310
+ return code, html_output