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.
- agentui/.prettierrc +15 -0
- agentui/QUICKSTART.md +272 -0
- agentui/README.md +59 -0
- agentui/env.example +16 -0
- agentui/jsconfig.json +14 -0
- agentui/package-lock.json +4242 -0
- agentui/package.json +34 -0
- agentui/scripts/postinstall/apply-patches.mjs +260 -0
- agentui/src/app.css +61 -0
- agentui/src/app.d.ts +13 -0
- agentui/src/app.html +12 -0
- agentui/src/components/LoadingSpinner.svelte +64 -0
- agentui/src/components/ThemeSwitcher.svelte +159 -0
- agentui/src/components/index.js +4 -0
- agentui/src/lib/api/bots.ts +60 -0
- agentui/src/lib/api/chat.ts +22 -0
- agentui/src/lib/api/http.ts +25 -0
- agentui/src/lib/components/BotCard.svelte +33 -0
- agentui/src/lib/components/ChatBubble.svelte +63 -0
- agentui/src/lib/components/Toast.svelte +21 -0
- agentui/src/lib/config.ts +20 -0
- agentui/src/lib/stores/auth.svelte.ts +73 -0
- agentui/src/lib/stores/theme.svelte.js +64 -0
- agentui/src/lib/stores/toast.svelte.ts +31 -0
- agentui/src/lib/utils/conversation.ts +39 -0
- agentui/src/routes/+layout.svelte +20 -0
- agentui/src/routes/+page.svelte +232 -0
- agentui/src/routes/login/+page.svelte +200 -0
- agentui/src/routes/talk/[agentId]/+page.svelte +297 -0
- agentui/src/routes/talk/[agentId]/+page.ts +7 -0
- agentui/static/README.md +1 -0
- agentui/svelte.config.js +11 -0
- agentui/tailwind.config.ts +53 -0
- agentui/tsconfig.json +3 -0
- agentui/vite.config.ts +10 -0
- ai_parrot-0.17.2.dist-info/METADATA +472 -0
- ai_parrot-0.17.2.dist-info/RECORD +535 -0
- ai_parrot-0.17.2.dist-info/WHEEL +6 -0
- ai_parrot-0.17.2.dist-info/entry_points.txt +2 -0
- ai_parrot-0.17.2.dist-info/licenses/LICENSE +21 -0
- ai_parrot-0.17.2.dist-info/top_level.txt +6 -0
- crew-builder/.prettierrc +15 -0
- crew-builder/QUICKSTART.md +259 -0
- crew-builder/README.md +113 -0
- crew-builder/env.example +17 -0
- crew-builder/jsconfig.json +14 -0
- crew-builder/package-lock.json +4182 -0
- crew-builder/package.json +37 -0
- crew-builder/scripts/postinstall/apply-patches.mjs +260 -0
- crew-builder/src/app.css +62 -0
- crew-builder/src/app.d.ts +13 -0
- crew-builder/src/app.html +12 -0
- crew-builder/src/components/LoadingSpinner.svelte +64 -0
- crew-builder/src/components/ThemeSwitcher.svelte +149 -0
- crew-builder/src/components/index.js +9 -0
- crew-builder/src/lib/api/bots.ts +60 -0
- crew-builder/src/lib/api/chat.ts +80 -0
- crew-builder/src/lib/api/client.ts +56 -0
- crew-builder/src/lib/api/crew/crew.ts +136 -0
- crew-builder/src/lib/api/index.ts +5 -0
- crew-builder/src/lib/api/o365/auth.ts +65 -0
- crew-builder/src/lib/auth/auth.ts +54 -0
- crew-builder/src/lib/components/AgentNode.svelte +43 -0
- crew-builder/src/lib/components/BotCard.svelte +33 -0
- crew-builder/src/lib/components/ChatBubble.svelte +67 -0
- crew-builder/src/lib/components/ConfigPanel.svelte +278 -0
- crew-builder/src/lib/components/JsonTreeNode.svelte +76 -0
- crew-builder/src/lib/components/JsonViewer.svelte +24 -0
- crew-builder/src/lib/components/MarkdownEditor.svelte +48 -0
- crew-builder/src/lib/components/ThemeToggle.svelte +36 -0
- crew-builder/src/lib/components/Toast.svelte +67 -0
- crew-builder/src/lib/components/Toolbar.svelte +157 -0
- crew-builder/src/lib/components/index.ts +10 -0
- crew-builder/src/lib/config.ts +8 -0
- crew-builder/src/lib/stores/auth.svelte.ts +228 -0
- crew-builder/src/lib/stores/crewStore.ts +369 -0
- crew-builder/src/lib/stores/theme.svelte.js +145 -0
- crew-builder/src/lib/stores/toast.svelte.ts +69 -0
- crew-builder/src/lib/utils/conversation.ts +39 -0
- crew-builder/src/lib/utils/markdown.ts +122 -0
- crew-builder/src/lib/utils/talkHistory.ts +47 -0
- crew-builder/src/routes/+layout.svelte +20 -0
- crew-builder/src/routes/+page.svelte +539 -0
- crew-builder/src/routes/agents/+page.svelte +247 -0
- crew-builder/src/routes/agents/[agentId]/+page.svelte +288 -0
- crew-builder/src/routes/agents/[agentId]/+page.ts +7 -0
- crew-builder/src/routes/builder/+page.svelte +204 -0
- crew-builder/src/routes/crew/ask/+page.svelte +1052 -0
- crew-builder/src/routes/crew/ask/+page.ts +1 -0
- crew-builder/src/routes/integrations/o365/+page.svelte +304 -0
- crew-builder/src/routes/login/+page.svelte +197 -0
- crew-builder/src/routes/talk/[agentId]/+page.svelte +487 -0
- crew-builder/src/routes/talk/[agentId]/+page.ts +7 -0
- crew-builder/static/README.md +1 -0
- crew-builder/svelte.config.js +11 -0
- crew-builder/tailwind.config.ts +53 -0
- crew-builder/tsconfig.json +3 -0
- crew-builder/vite.config.ts +10 -0
- mcp_servers/calculator_server.py +309 -0
- parrot/__init__.py +27 -0
- parrot/__pycache__/__init__.cpython-310.pyc +0 -0
- parrot/__pycache__/version.cpython-310.pyc +0 -0
- parrot/_version.py +34 -0
- parrot/a2a/__init__.py +48 -0
- parrot/a2a/client.py +658 -0
- parrot/a2a/discovery.py +89 -0
- parrot/a2a/mixin.py +257 -0
- parrot/a2a/models.py +376 -0
- parrot/a2a/server.py +770 -0
- parrot/agents/__init__.py +29 -0
- parrot/bots/__init__.py +12 -0
- parrot/bots/a2a_agent.py +19 -0
- parrot/bots/abstract.py +3139 -0
- parrot/bots/agent.py +1129 -0
- parrot/bots/basic.py +9 -0
- parrot/bots/chatbot.py +669 -0
- parrot/bots/data.py +1618 -0
- parrot/bots/database/__init__.py +5 -0
- parrot/bots/database/abstract.py +3071 -0
- parrot/bots/database/cache.py +286 -0
- parrot/bots/database/models.py +468 -0
- parrot/bots/database/prompts.py +154 -0
- parrot/bots/database/retries.py +98 -0
- parrot/bots/database/router.py +269 -0
- parrot/bots/database/sql.py +41 -0
- parrot/bots/db/__init__.py +6 -0
- parrot/bots/db/abstract.py +556 -0
- parrot/bots/db/bigquery.py +602 -0
- parrot/bots/db/cache.py +85 -0
- parrot/bots/db/documentdb.py +668 -0
- parrot/bots/db/elastic.py +1014 -0
- parrot/bots/db/influx.py +898 -0
- parrot/bots/db/mock.py +96 -0
- parrot/bots/db/multi.py +783 -0
- parrot/bots/db/prompts.py +185 -0
- parrot/bots/db/sql.py +1255 -0
- parrot/bots/db/tools.py +212 -0
- parrot/bots/document.py +680 -0
- parrot/bots/hrbot.py +15 -0
- parrot/bots/kb.py +170 -0
- parrot/bots/mcp.py +36 -0
- parrot/bots/orchestration/README.md +463 -0
- parrot/bots/orchestration/__init__.py +1 -0
- parrot/bots/orchestration/agent.py +155 -0
- parrot/bots/orchestration/crew.py +3330 -0
- parrot/bots/orchestration/fsm.py +1179 -0
- parrot/bots/orchestration/hr.py +434 -0
- parrot/bots/orchestration/storage/__init__.py +4 -0
- parrot/bots/orchestration/storage/memory.py +100 -0
- parrot/bots/orchestration/storage/mixin.py +119 -0
- parrot/bots/orchestration/verify.py +202 -0
- parrot/bots/product.py +204 -0
- parrot/bots/prompts/__init__.py +96 -0
- parrot/bots/prompts/agents.py +155 -0
- parrot/bots/prompts/data.py +216 -0
- parrot/bots/prompts/output_generation.py +8 -0
- parrot/bots/scraper/__init__.py +3 -0
- parrot/bots/scraper/models.py +122 -0
- parrot/bots/scraper/scraper.py +1173 -0
- parrot/bots/scraper/templates.py +115 -0
- parrot/bots/stores/__init__.py +5 -0
- parrot/bots/stores/local.py +172 -0
- parrot/bots/webdev.py +81 -0
- parrot/cli.py +17 -0
- parrot/clients/__init__.py +16 -0
- parrot/clients/base.py +1491 -0
- parrot/clients/claude.py +1191 -0
- parrot/clients/factory.py +129 -0
- parrot/clients/google.py +4567 -0
- parrot/clients/gpt.py +1975 -0
- parrot/clients/grok.py +432 -0
- parrot/clients/groq.py +986 -0
- parrot/clients/hf.py +582 -0
- parrot/clients/models.py +18 -0
- parrot/conf.py +395 -0
- parrot/embeddings/__init__.py +9 -0
- parrot/embeddings/base.py +157 -0
- parrot/embeddings/google.py +98 -0
- parrot/embeddings/huggingface.py +74 -0
- parrot/embeddings/openai.py +84 -0
- parrot/embeddings/processor.py +88 -0
- parrot/exceptions.c +13868 -0
- parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/exceptions.pxd +22 -0
- parrot/exceptions.pxi +15 -0
- parrot/exceptions.pyx +44 -0
- parrot/generators/__init__.py +29 -0
- parrot/generators/base.py +200 -0
- parrot/generators/html.py +293 -0
- parrot/generators/react.py +205 -0
- parrot/generators/streamlit.py +203 -0
- parrot/generators/template.py +105 -0
- parrot/handlers/__init__.py +4 -0
- parrot/handlers/agent.py +861 -0
- parrot/handlers/agents/__init__.py +1 -0
- parrot/handlers/agents/abstract.py +900 -0
- parrot/handlers/bots.py +338 -0
- parrot/handlers/chat.py +915 -0
- parrot/handlers/creation.sql +192 -0
- parrot/handlers/crew/ARCHITECTURE.md +362 -0
- parrot/handlers/crew/README_BOTMANAGER_PERSISTENCE.md +303 -0
- parrot/handlers/crew/README_REDIS_PERSISTENCE.md +366 -0
- parrot/handlers/crew/__init__.py +0 -0
- parrot/handlers/crew/handler.py +801 -0
- parrot/handlers/crew/models.py +229 -0
- parrot/handlers/crew/redis_persistence.py +523 -0
- parrot/handlers/jobs/__init__.py +10 -0
- parrot/handlers/jobs/job.py +384 -0
- parrot/handlers/jobs/mixin.py +627 -0
- parrot/handlers/jobs/models.py +115 -0
- parrot/handlers/jobs/worker.py +31 -0
- parrot/handlers/models.py +596 -0
- parrot/handlers/o365_auth.py +105 -0
- parrot/handlers/stream.py +337 -0
- parrot/interfaces/__init__.py +6 -0
- parrot/interfaces/aws.py +143 -0
- parrot/interfaces/credentials.py +113 -0
- parrot/interfaces/database.py +27 -0
- parrot/interfaces/google.py +1123 -0
- parrot/interfaces/hierarchy.py +1227 -0
- parrot/interfaces/http.py +651 -0
- parrot/interfaces/images/__init__.py +0 -0
- parrot/interfaces/images/plugins/__init__.py +24 -0
- parrot/interfaces/images/plugins/abstract.py +58 -0
- parrot/interfaces/images/plugins/analisys.py +148 -0
- parrot/interfaces/images/plugins/classify.py +150 -0
- parrot/interfaces/images/plugins/classifybase.py +182 -0
- parrot/interfaces/images/plugins/detect.py +150 -0
- parrot/interfaces/images/plugins/exif.py +1103 -0
- parrot/interfaces/images/plugins/hash.py +52 -0
- parrot/interfaces/images/plugins/vision.py +104 -0
- parrot/interfaces/images/plugins/yolo.py +66 -0
- parrot/interfaces/images/plugins/zerodetect.py +197 -0
- parrot/interfaces/o365.py +978 -0
- parrot/interfaces/onedrive.py +822 -0
- parrot/interfaces/sharepoint.py +1435 -0
- parrot/interfaces/soap.py +257 -0
- parrot/loaders/__init__.py +8 -0
- parrot/loaders/abstract.py +1131 -0
- parrot/loaders/audio.py +199 -0
- parrot/loaders/basepdf.py +53 -0
- parrot/loaders/basevideo.py +1568 -0
- parrot/loaders/csv.py +409 -0
- parrot/loaders/docx.py +116 -0
- parrot/loaders/epubloader.py +316 -0
- parrot/loaders/excel.py +199 -0
- parrot/loaders/factory.py +55 -0
- parrot/loaders/files/__init__.py +0 -0
- parrot/loaders/files/abstract.py +39 -0
- parrot/loaders/files/html.py +26 -0
- parrot/loaders/files/text.py +63 -0
- parrot/loaders/html.py +152 -0
- parrot/loaders/markdown.py +442 -0
- parrot/loaders/pdf.py +373 -0
- parrot/loaders/pdfmark.py +320 -0
- parrot/loaders/pdftables.py +506 -0
- parrot/loaders/ppt.py +476 -0
- parrot/loaders/qa.py +63 -0
- parrot/loaders/splitters/__init__.py +10 -0
- parrot/loaders/splitters/base.py +138 -0
- parrot/loaders/splitters/md.py +228 -0
- parrot/loaders/splitters/token.py +143 -0
- parrot/loaders/txt.py +26 -0
- parrot/loaders/video.py +89 -0
- parrot/loaders/videolocal.py +218 -0
- parrot/loaders/videounderstanding.py +377 -0
- parrot/loaders/vimeo.py +167 -0
- parrot/loaders/web.py +599 -0
- parrot/loaders/youtube.py +504 -0
- parrot/manager/__init__.py +5 -0
- parrot/manager/manager.py +1030 -0
- parrot/mcp/__init__.py +28 -0
- parrot/mcp/adapter.py +105 -0
- parrot/mcp/cli.py +174 -0
- parrot/mcp/client.py +119 -0
- parrot/mcp/config.py +75 -0
- parrot/mcp/integration.py +842 -0
- parrot/mcp/oauth.py +933 -0
- parrot/mcp/server.py +225 -0
- parrot/mcp/transports/__init__.py +3 -0
- parrot/mcp/transports/base.py +279 -0
- parrot/mcp/transports/grpc_session.py +163 -0
- parrot/mcp/transports/http.py +312 -0
- parrot/mcp/transports/mcp.proto +108 -0
- parrot/mcp/transports/quic.py +1082 -0
- parrot/mcp/transports/sse.py +330 -0
- parrot/mcp/transports/stdio.py +309 -0
- parrot/mcp/transports/unix.py +395 -0
- parrot/mcp/transports/websocket.py +547 -0
- parrot/memory/__init__.py +16 -0
- parrot/memory/abstract.py +209 -0
- parrot/memory/agent.py +32 -0
- parrot/memory/cache.py +175 -0
- parrot/memory/core.py +555 -0
- parrot/memory/file.py +153 -0
- parrot/memory/mem.py +131 -0
- parrot/memory/redis.py +613 -0
- parrot/models/__init__.py +46 -0
- parrot/models/basic.py +118 -0
- parrot/models/compliance.py +208 -0
- parrot/models/crew.py +395 -0
- parrot/models/detections.py +654 -0
- parrot/models/generation.py +85 -0
- parrot/models/google.py +223 -0
- parrot/models/groq.py +23 -0
- parrot/models/openai.py +30 -0
- parrot/models/outputs.py +285 -0
- parrot/models/responses.py +938 -0
- parrot/notifications/__init__.py +743 -0
- parrot/openapi/__init__.py +3 -0
- parrot/openapi/components.yaml +641 -0
- parrot/openapi/config.py +322 -0
- parrot/outputs/__init__.py +32 -0
- parrot/outputs/formats/__init__.py +108 -0
- parrot/outputs/formats/altair.py +359 -0
- parrot/outputs/formats/application.py +122 -0
- parrot/outputs/formats/base.py +351 -0
- parrot/outputs/formats/bokeh.py +356 -0
- parrot/outputs/formats/card.py +424 -0
- parrot/outputs/formats/chart.py +436 -0
- parrot/outputs/formats/d3.py +255 -0
- parrot/outputs/formats/echarts.py +310 -0
- parrot/outputs/formats/generators/__init__.py +0 -0
- parrot/outputs/formats/generators/abstract.py +61 -0
- parrot/outputs/formats/generators/panel.py +145 -0
- parrot/outputs/formats/generators/streamlit.py +86 -0
- parrot/outputs/formats/generators/terminal.py +63 -0
- parrot/outputs/formats/holoviews.py +310 -0
- parrot/outputs/formats/html.py +147 -0
- parrot/outputs/formats/jinja2.py +46 -0
- parrot/outputs/formats/json.py +87 -0
- parrot/outputs/formats/map.py +933 -0
- parrot/outputs/formats/markdown.py +172 -0
- parrot/outputs/formats/matplotlib.py +237 -0
- parrot/outputs/formats/mixins/__init__.py +0 -0
- parrot/outputs/formats/mixins/emaps.py +855 -0
- parrot/outputs/formats/plotly.py +341 -0
- parrot/outputs/formats/seaborn.py +310 -0
- parrot/outputs/formats/table.py +397 -0
- parrot/outputs/formats/template_report.py +138 -0
- parrot/outputs/formats/yaml.py +125 -0
- parrot/outputs/formatter.py +152 -0
- parrot/outputs/templates/__init__.py +95 -0
- parrot/pipelines/__init__.py +0 -0
- parrot/pipelines/abstract.py +210 -0
- parrot/pipelines/detector.py +124 -0
- parrot/pipelines/models.py +90 -0
- parrot/pipelines/planogram.py +3002 -0
- parrot/pipelines/table.sql +97 -0
- parrot/plugins/__init__.py +106 -0
- parrot/plugins/importer.py +80 -0
- parrot/py.typed +0 -0
- parrot/registry/__init__.py +18 -0
- parrot/registry/registry.py +594 -0
- parrot/scheduler/__init__.py +1189 -0
- parrot/scheduler/models.py +60 -0
- parrot/security/__init__.py +16 -0
- parrot/security/prompt_injection.py +268 -0
- parrot/security/security_events.sql +25 -0
- parrot/services/__init__.py +1 -0
- parrot/services/mcp/__init__.py +8 -0
- parrot/services/mcp/config.py +13 -0
- parrot/services/mcp/server.py +295 -0
- parrot/services/o365_remote_auth.py +235 -0
- parrot/stores/__init__.py +7 -0
- parrot/stores/abstract.py +352 -0
- parrot/stores/arango.py +1090 -0
- parrot/stores/bigquery.py +1377 -0
- parrot/stores/cache.py +106 -0
- parrot/stores/empty.py +10 -0
- parrot/stores/faiss_store.py +1157 -0
- parrot/stores/kb/__init__.py +9 -0
- parrot/stores/kb/abstract.py +68 -0
- parrot/stores/kb/cache.py +165 -0
- parrot/stores/kb/doc.py +325 -0
- parrot/stores/kb/hierarchy.py +346 -0
- parrot/stores/kb/local.py +457 -0
- parrot/stores/kb/prompt.py +28 -0
- parrot/stores/kb/redis.py +659 -0
- parrot/stores/kb/store.py +115 -0
- parrot/stores/kb/user.py +374 -0
- parrot/stores/models.py +59 -0
- parrot/stores/pgvector.py +3 -0
- parrot/stores/postgres.py +2853 -0
- parrot/stores/utils/__init__.py +0 -0
- parrot/stores/utils/chunking.py +197 -0
- parrot/telemetry/__init__.py +3 -0
- parrot/telemetry/mixin.py +111 -0
- parrot/template/__init__.py +3 -0
- parrot/template/engine.py +259 -0
- parrot/tools/__init__.py +23 -0
- parrot/tools/abstract.py +644 -0
- parrot/tools/agent.py +363 -0
- parrot/tools/arangodbsearch.py +537 -0
- parrot/tools/arxiv_tool.py +188 -0
- parrot/tools/calculator/__init__.py +3 -0
- parrot/tools/calculator/operations/__init__.py +38 -0
- parrot/tools/calculator/operations/calculus.py +80 -0
- parrot/tools/calculator/operations/statistics.py +76 -0
- parrot/tools/calculator/tool.py +150 -0
- parrot/tools/cloudwatch.py +988 -0
- parrot/tools/codeinterpreter/__init__.py +127 -0
- parrot/tools/codeinterpreter/executor.py +371 -0
- parrot/tools/codeinterpreter/internals.py +473 -0
- parrot/tools/codeinterpreter/models.py +643 -0
- parrot/tools/codeinterpreter/prompts.py +224 -0
- parrot/tools/codeinterpreter/tool.py +664 -0
- parrot/tools/company_info/__init__.py +6 -0
- parrot/tools/company_info/tool.py +1138 -0
- parrot/tools/correlationanalysis.py +437 -0
- parrot/tools/database/abstract.py +286 -0
- parrot/tools/database/bq.py +115 -0
- parrot/tools/database/cache.py +284 -0
- parrot/tools/database/models.py +95 -0
- parrot/tools/database/pg.py +343 -0
- parrot/tools/databasequery.py +1159 -0
- parrot/tools/db.py +1800 -0
- parrot/tools/ddgo.py +370 -0
- parrot/tools/decorators.py +271 -0
- parrot/tools/dftohtml.py +282 -0
- parrot/tools/document.py +549 -0
- parrot/tools/ecs.py +819 -0
- parrot/tools/edareport.py +368 -0
- parrot/tools/elasticsearch.py +1049 -0
- parrot/tools/employees.py +462 -0
- parrot/tools/epson/__init__.py +96 -0
- parrot/tools/excel.py +683 -0
- parrot/tools/file/__init__.py +13 -0
- parrot/tools/file/abstract.py +76 -0
- parrot/tools/file/gcs.py +378 -0
- parrot/tools/file/local.py +284 -0
- parrot/tools/file/s3.py +511 -0
- parrot/tools/file/tmp.py +309 -0
- parrot/tools/file/tool.py +501 -0
- parrot/tools/file_reader.py +129 -0
- parrot/tools/flowtask/__init__.py +19 -0
- parrot/tools/flowtask/tool.py +761 -0
- parrot/tools/gittoolkit.py +508 -0
- parrot/tools/google/__init__.py +18 -0
- parrot/tools/google/base.py +169 -0
- parrot/tools/google/tools.py +1251 -0
- parrot/tools/googlelocation.py +5 -0
- parrot/tools/googleroutes.py +5 -0
- parrot/tools/googlesearch.py +5 -0
- parrot/tools/googlesitesearch.py +5 -0
- parrot/tools/googlevoice.py +2 -0
- parrot/tools/gvoice.py +695 -0
- parrot/tools/ibisworld/README.md +225 -0
- parrot/tools/ibisworld/__init__.py +11 -0
- parrot/tools/ibisworld/tool.py +366 -0
- parrot/tools/jiratoolkit.py +1718 -0
- parrot/tools/manager.py +1098 -0
- parrot/tools/math.py +152 -0
- parrot/tools/metadata.py +476 -0
- parrot/tools/msteams.py +1621 -0
- parrot/tools/msword.py +635 -0
- parrot/tools/multidb.py +580 -0
- parrot/tools/multistoresearch.py +369 -0
- parrot/tools/networkninja.py +167 -0
- parrot/tools/nextstop/__init__.py +4 -0
- parrot/tools/nextstop/base.py +286 -0
- parrot/tools/nextstop/employee.py +733 -0
- parrot/tools/nextstop/store.py +462 -0
- parrot/tools/notification.py +435 -0
- parrot/tools/o365/__init__.py +42 -0
- parrot/tools/o365/base.py +295 -0
- parrot/tools/o365/bundle.py +522 -0
- parrot/tools/o365/events.py +554 -0
- parrot/tools/o365/mail.py +992 -0
- parrot/tools/o365/onedrive.py +497 -0
- parrot/tools/o365/sharepoint.py +641 -0
- parrot/tools/openapi_toolkit.py +904 -0
- parrot/tools/openweather.py +527 -0
- parrot/tools/pdfprint.py +1001 -0
- parrot/tools/powerbi.py +518 -0
- parrot/tools/powerpoint.py +1113 -0
- parrot/tools/pricestool.py +146 -0
- parrot/tools/products/__init__.py +246 -0
- parrot/tools/prophet_tool.py +171 -0
- parrot/tools/pythonpandas.py +630 -0
- parrot/tools/pythonrepl.py +910 -0
- parrot/tools/qsource.py +436 -0
- parrot/tools/querytoolkit.py +395 -0
- parrot/tools/quickeda.py +827 -0
- parrot/tools/resttool.py +553 -0
- parrot/tools/retail/__init__.py +0 -0
- parrot/tools/retail/bby.py +528 -0
- parrot/tools/sandboxtool.py +703 -0
- parrot/tools/sassie/__init__.py +352 -0
- parrot/tools/scraping/__init__.py +7 -0
- parrot/tools/scraping/docs/select.md +466 -0
- parrot/tools/scraping/documentation.md +1278 -0
- parrot/tools/scraping/driver.py +436 -0
- parrot/tools/scraping/models.py +576 -0
- parrot/tools/scraping/options.py +85 -0
- parrot/tools/scraping/orchestrator.py +517 -0
- parrot/tools/scraping/readme.md +740 -0
- parrot/tools/scraping/tool.py +3115 -0
- parrot/tools/seasonaldetection.py +642 -0
- parrot/tools/shell_tool/__init__.py +5 -0
- parrot/tools/shell_tool/actions.py +408 -0
- parrot/tools/shell_tool/engine.py +155 -0
- parrot/tools/shell_tool/models.py +322 -0
- parrot/tools/shell_tool/tool.py +442 -0
- parrot/tools/site_search.py +214 -0
- parrot/tools/textfile.py +418 -0
- parrot/tools/think.py +378 -0
- parrot/tools/toolkit.py +298 -0
- parrot/tools/webapp_tool.py +187 -0
- parrot/tools/whatif.py +1279 -0
- parrot/tools/workday/MULTI_WSDL_EXAMPLE.md +249 -0
- parrot/tools/workday/__init__.py +6 -0
- parrot/tools/workday/models.py +1389 -0
- parrot/tools/workday/tool.py +1293 -0
- parrot/tools/yfinance_tool.py +306 -0
- parrot/tools/zipcode.py +217 -0
- parrot/utils/__init__.py +2 -0
- parrot/utils/helpers.py +73 -0
- parrot/utils/parsers/__init__.py +5 -0
- parrot/utils/parsers/toml.c +12078 -0
- parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/utils/parsers/toml.pyx +21 -0
- parrot/utils/toml.py +11 -0
- parrot/utils/types.cpp +20936 -0
- parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
- parrot/utils/types.pyx +213 -0
- parrot/utils/uv.py +11 -0
- parrot/version.py +10 -0
- parrot/yaml-rs/Cargo.lock +350 -0
- parrot/yaml-rs/Cargo.toml +19 -0
- parrot/yaml-rs/pyproject.toml +19 -0
- parrot/yaml-rs/python/yaml_rs/__init__.py +81 -0
- parrot/yaml-rs/src/lib.rs +222 -0
- requirements/docker-compose.yml +24 -0
- 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
|