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