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,310 @@
|
|
|
1
|
+
from typing import Any, Optional, Tuple, Dict, List
|
|
2
|
+
import uuid
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import json
|
|
5
|
+
from .chart import BaseChart
|
|
6
|
+
from . import register_renderer
|
|
7
|
+
from ...models.outputs import OutputMode
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
import holoviews as hv
|
|
11
|
+
from bokeh.embed import components
|
|
12
|
+
from bokeh.resources import CDN
|
|
13
|
+
HOLOVIEWS_AVAILABLE = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
HOLOVIEWS_AVAILABLE = False
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
from rich.panel import Panel
|
|
19
|
+
RICH_AVAILABLE = True
|
|
20
|
+
except ImportError:
|
|
21
|
+
RICH_AVAILABLE = False
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
from ipywidgets import HTML as IPyHTML
|
|
25
|
+
IPYWIDGETS_AVAILABLE = True
|
|
26
|
+
except ImportError:
|
|
27
|
+
IPYWIDGETS_AVAILABLE = False
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
HOLOVIEWS_SYSTEM_PROMPT = """HOLOVIEWS CHART OUTPUT MODE:
|
|
31
|
+
Generate interactive charts using HoloViews (typically with Bokeh backend).
|
|
32
|
+
|
|
33
|
+
REQUIREMENTS:
|
|
34
|
+
1. Return Python code in a markdown code block (```python).
|
|
35
|
+
2. MANDATORY: Start by importing holoviews and loading the extension:
|
|
36
|
+
```python
|
|
37
|
+
import holoviews as hv
|
|
38
|
+
from holoviews import opts
|
|
39
|
+
hv.extension('bokeh')
|
|
40
|
+
3. Store the final layout/element in a variable named 'chart', 'plot', 'layout', or 'fig'
|
|
41
|
+
4. Make the chart self-contained with inline data (pandas or lists)
|
|
42
|
+
5. CHART TYPES:
|
|
43
|
+
- PREFERRED: hv.Bars, hv.Curve, hv.Scatter, hv.HeatMap, hv.Histogram.
|
|
44
|
+
- FORBIDDEN: Do NOT use hv.Pie. If the user asks for a Pie chart, you MUST generate a hv.Bars chart instead.
|
|
45
|
+
6. Use hv.opts for styling (width, height, tools, etc.)
|
|
46
|
+
7. DO NOT execute the code or save files - return code only
|
|
47
|
+
|
|
48
|
+
EXAMPLE:
|
|
49
|
+
```python
|
|
50
|
+
import pandas as pd
|
|
51
|
+
import holoviews as hv
|
|
52
|
+
from holoviews import opts
|
|
53
|
+
hv.extension('bokeh')
|
|
54
|
+
|
|
55
|
+
# Data
|
|
56
|
+
data = pd.DataFrame({
|
|
57
|
+
'cyl': [4, 6, 8, 4, 6, 8],
|
|
58
|
+
'mpg': [30, 20, 15, 32, 21, 14]
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
# Plot
|
|
62
|
+
hist = hv.Histogram(data, kdims='mpg', vdims='cyl')
|
|
63
|
+
hist.opts(opts.Histogram(alpha=0.9, width=600, height=400, title="MPG Histogram"))
|
|
64
|
+
|
|
65
|
+
# Assign to variable
|
|
66
|
+
chart = hist
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
@register_renderer(OutputMode.HOLOVIEWS, system_prompt=HOLOVIEWS_SYSTEM_PROMPT)
|
|
70
|
+
class HoloviewsRenderer(BaseChart):
|
|
71
|
+
"""Renderer for HoloViews charts (via Bokeh backend)"""
|
|
72
|
+
|
|
73
|
+
def execute_code(
|
|
74
|
+
self,
|
|
75
|
+
code: str,
|
|
76
|
+
pandas_tool: Any = None,
|
|
77
|
+
execution_state: Optional[Dict[str, Any]] = None,
|
|
78
|
+
**kwargs,
|
|
79
|
+
) -> Tuple[Any, Optional[str]]:
|
|
80
|
+
"""Execute HoloViews code within the shared Python environment."""
|
|
81
|
+
|
|
82
|
+
if not HOLOVIEWS_AVAILABLE:
|
|
83
|
+
return None, "HoloViews or Bokeh not installed. Please install: pip install holoviews bokeh"
|
|
84
|
+
|
|
85
|
+
# Execute using BaseRenderer logic
|
|
86
|
+
context, error = super().execute_code(
|
|
87
|
+
code,
|
|
88
|
+
pandas_tool=pandas_tool,
|
|
89
|
+
execution_state=execution_state,
|
|
90
|
+
**kwargs,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if error:
|
|
94
|
+
return None, error
|
|
95
|
+
|
|
96
|
+
if not context:
|
|
97
|
+
return None, "Execution context was empty"
|
|
98
|
+
|
|
99
|
+
# Find the chart objects
|
|
100
|
+
if figures := self._find_chart_objects(context):
|
|
101
|
+
return figures, None
|
|
102
|
+
|
|
103
|
+
return None, "Code must define a HoloViews object (chart, plot, layout)"
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def _find_chart_objects(context: Dict[str, Any]) -> List[Any]:
|
|
107
|
+
"""Locate all HoloViews objects in the local namespace."""
|
|
108
|
+
figures: List[Any] = []
|
|
109
|
+
seen_ids = set()
|
|
110
|
+
|
|
111
|
+
def add_fig(obj: Any) -> None:
|
|
112
|
+
if obj is None:
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
# Robust Check: Use isinstance if library is loaded, otherwise strict duck-typing
|
|
116
|
+
is_holoviews = False
|
|
117
|
+
if HOLOVIEWS_AVAILABLE:
|
|
118
|
+
# hv.core.Dimensioned is the base for Elements, Layouts, Overlays
|
|
119
|
+
if isinstance(obj, hv.core.Dimensioned):
|
|
120
|
+
is_holoviews = True
|
|
121
|
+
|
|
122
|
+
# Fallback duck-typing if isinstance fails or library mix-up
|
|
123
|
+
if not is_holoviews:
|
|
124
|
+
# Relaxed duck-typing: check for 'opts' and 'kdims' OR 'data' (some containers)
|
|
125
|
+
if hasattr(obj, 'opts') and (hasattr(obj, 'kdims') or hasattr(obj, 'data')):
|
|
126
|
+
is_holoviews = True
|
|
127
|
+
|
|
128
|
+
if is_holoviews and id(obj) not in seen_ids:
|
|
129
|
+
figures.append(obj)
|
|
130
|
+
seen_ids.add(id(obj))
|
|
131
|
+
|
|
132
|
+
# 1. Priority search for named variables
|
|
133
|
+
priority_vars = ['chart', 'plot', 'layout', 'fig', 'renderer', 'pie_chart', 'bar_chart']
|
|
134
|
+
for var_name in priority_vars:
|
|
135
|
+
if var_name in context:
|
|
136
|
+
add_fig(context[var_name])
|
|
137
|
+
|
|
138
|
+
# 2. Scan all locals for other figure objects
|
|
139
|
+
for var_name, obj in context.items():
|
|
140
|
+
if var_name.startswith('_') or var_name in priority_vars:
|
|
141
|
+
continue
|
|
142
|
+
# Skip modules and basic types to save time
|
|
143
|
+
if isinstance(obj, (int, float, str, bool, type(None))):
|
|
144
|
+
continue
|
|
145
|
+
add_fig(obj)
|
|
146
|
+
|
|
147
|
+
return figures
|
|
148
|
+
|
|
149
|
+
def _render_chart_content(self, chart_objs: Any, **kwargs) -> str:
|
|
150
|
+
"""
|
|
151
|
+
Render HoloViews object to HTML/JS using Bokeh backend.
|
|
152
|
+
"""
|
|
153
|
+
if not HOLOVIEWS_AVAILABLE:
|
|
154
|
+
return "<div>HoloViews library not available.</div>"
|
|
155
|
+
|
|
156
|
+
# Ensure we have a list
|
|
157
|
+
figures = chart_objs if isinstance(chart_objs, list) else [chart_objs]
|
|
158
|
+
html_parts = []
|
|
159
|
+
|
|
160
|
+
# Ensure the bokeh extension is loaded
|
|
161
|
+
try:
|
|
162
|
+
# We try to set it silent to avoid console spam
|
|
163
|
+
hv.extension('bokeh', logo=False)
|
|
164
|
+
renderer = hv.renderer('bokeh')
|
|
165
|
+
except Exception:
|
|
166
|
+
# Fallback
|
|
167
|
+
renderer = hv.renderer('bokeh')
|
|
168
|
+
|
|
169
|
+
for fig in figures:
|
|
170
|
+
try:
|
|
171
|
+
# 1. Render HoloViews object to a Bokeh plot
|
|
172
|
+
plot_state = renderer.get_plot(fig)
|
|
173
|
+
|
|
174
|
+
# 2. Generate Script and Div using Bokeh's components
|
|
175
|
+
script, div = components(plot_state.state)
|
|
176
|
+
|
|
177
|
+
# 3. Combine them
|
|
178
|
+
chart_html = f'''
|
|
179
|
+
<div class="holoviews-chart-wrapper" style="margin-bottom: 20px; display: flex; justify-content: center; flex-direction: column; align-items: center;">
|
|
180
|
+
{div}
|
|
181
|
+
{script}
|
|
182
|
+
</div>
|
|
183
|
+
'''
|
|
184
|
+
html_parts.append(chart_html)
|
|
185
|
+
|
|
186
|
+
except Exception as e:
|
|
187
|
+
html_parts.append(f'<div class="error" style="color:red; padding:10px;">Error rendering HoloViews chart: {str(e)}</div>')
|
|
188
|
+
|
|
189
|
+
return "\n".join(html_parts)
|
|
190
|
+
|
|
191
|
+
def _save_to_disk(self, chart_objs: Any, filename: str = None) -> str:
|
|
192
|
+
"""Save chart(s) to HTML file for terminal viewing."""
|
|
193
|
+
if not filename:
|
|
194
|
+
filename = f"holoviews_{uuid.uuid4().hex[:8]}.html"
|
|
195
|
+
|
|
196
|
+
output_dir = Path("outputs/charts")
|
|
197
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
198
|
+
filepath = output_dir / filename
|
|
199
|
+
|
|
200
|
+
if not HOLOVIEWS_AVAILABLE:
|
|
201
|
+
return "Error: HoloViews not installed"
|
|
202
|
+
|
|
203
|
+
figures = chart_objs if isinstance(chart_objs, list) else [chart_objs]
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
# Use HoloViews save method (which handles the HTML boilerplate)
|
|
207
|
+
# If multiple figures, we might want to wrap them in a Layout if possible,
|
|
208
|
+
# but saving individually or the last one is standard fallback.
|
|
209
|
+
# Here we combine them if there are multiple.
|
|
210
|
+
|
|
211
|
+
final_obj = figures[0]
|
|
212
|
+
if len(figures) > 1:
|
|
213
|
+
final_obj = hv.Layout(figures).cols(1)
|
|
214
|
+
|
|
215
|
+
hv.save(final_obj, filepath, backend='bokeh')
|
|
216
|
+
return str(filepath)
|
|
217
|
+
except Exception as e:
|
|
218
|
+
raise e
|
|
219
|
+
|
|
220
|
+
def to_html(
|
|
221
|
+
self,
|
|
222
|
+
chart_obj: Any,
|
|
223
|
+
mode: str = 'partial',
|
|
224
|
+
**kwargs
|
|
225
|
+
) -> str:
|
|
226
|
+
"""
|
|
227
|
+
Convert HoloViews chart(s) to HTML.
|
|
228
|
+
"""
|
|
229
|
+
# Generate Bokeh JS/CSS resources for the <head>
|
|
230
|
+
# This is crucial for the scripts in _render_chart_content to work
|
|
231
|
+
extra_head = CDN.render() if HOLOVIEWS_AVAILABLE else ""
|
|
232
|
+
|
|
233
|
+
kwargs['extra_head'] = kwargs.get('extra_head', '') + "\n" + extra_head
|
|
234
|
+
|
|
235
|
+
return super().to_html(chart_obj, mode=mode, **kwargs)
|
|
236
|
+
|
|
237
|
+
async def render(
|
|
238
|
+
self,
|
|
239
|
+
response: Any,
|
|
240
|
+
theme: str = 'monokai',
|
|
241
|
+
environment: str = 'html',
|
|
242
|
+
include_code: bool = False,
|
|
243
|
+
html_mode: str = 'partial',
|
|
244
|
+
**kwargs
|
|
245
|
+
) -> Tuple[Any, Optional[Any]]:
|
|
246
|
+
"""Render HoloViews chart."""
|
|
247
|
+
|
|
248
|
+
# 1. Extract Code
|
|
249
|
+
code = getattr(response, 'code', None)
|
|
250
|
+
output_format = kwargs.get('output_format', environment)
|
|
251
|
+
|
|
252
|
+
if not code:
|
|
253
|
+
content = self._get_content(response)
|
|
254
|
+
code = self._extract_code(content)
|
|
255
|
+
|
|
256
|
+
if not code:
|
|
257
|
+
error_msg = "No chart code found in response"
|
|
258
|
+
if output_format == 'terminal':
|
|
259
|
+
return error_msg, None
|
|
260
|
+
return self._wrap_for_environment(
|
|
261
|
+
f"<div class='error'>{error_msg}</div>", output_format
|
|
262
|
+
), None
|
|
263
|
+
|
|
264
|
+
# 2. Execute Code
|
|
265
|
+
chart_objs, error = self.execute_code(
|
|
266
|
+
code,
|
|
267
|
+
pandas_tool=kwargs.pop('pandas_tool', None),
|
|
268
|
+
execution_state=kwargs.pop('execution_state', None),
|
|
269
|
+
**kwargs,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
if error:
|
|
273
|
+
if output_format == 'terminal':
|
|
274
|
+
return f"Error generating chart: {error}", None
|
|
275
|
+
return self._wrap_for_environment(
|
|
276
|
+
self._render_error(error, code, theme), output_format
|
|
277
|
+
), None
|
|
278
|
+
|
|
279
|
+
# 3. Handle Terminal Environment (Save to Disk)
|
|
280
|
+
if output_format == 'terminal':
|
|
281
|
+
try:
|
|
282
|
+
saved_path = self._save_to_disk(chart_objs)
|
|
283
|
+
msg = f"Interactive HoloViews chart saved to: {saved_path}"
|
|
284
|
+
if RICH_AVAILABLE:
|
|
285
|
+
return Panel(msg, title="📊 HoloViews Chart", border_style="green"), None
|
|
286
|
+
return msg, None
|
|
287
|
+
except Exception as e:
|
|
288
|
+
return f"Chart generated but failed to save: {e}", None
|
|
289
|
+
|
|
290
|
+
# 4. Generate HTML
|
|
291
|
+
# Pass title and other kwargs to to_html
|
|
292
|
+
html_output = self.to_html(
|
|
293
|
+
chart_objs,
|
|
294
|
+
mode=html_mode,
|
|
295
|
+
include_code=include_code,
|
|
296
|
+
code=code,
|
|
297
|
+
theme=theme,
|
|
298
|
+
title=kwargs.get('title', 'HoloViews Chart'),
|
|
299
|
+
icon='📈',
|
|
300
|
+
**kwargs
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
# 5. Wrap for Environment
|
|
304
|
+
if output_format in {'jupyter', 'notebook', 'ipython', 'colab'}:
|
|
305
|
+
if IPYWIDGETS_AVAILABLE:
|
|
306
|
+
return code, IPyHTML(value=html_output)
|
|
307
|
+
return code, html_output
|
|
308
|
+
|
|
309
|
+
# 6. Return default
|
|
310
|
+
return code, html_output
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
from typing import Any, List, Tuple, Optional
|
|
2
|
+
import tempfile
|
|
3
|
+
import os
|
|
4
|
+
from . import register_renderer
|
|
5
|
+
from .base import BaseRenderer
|
|
6
|
+
from ...models.outputs import OutputMode
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
import panel as pn
|
|
10
|
+
from panel.pane import Markdown as PanelMarkdown
|
|
11
|
+
from panel.layout import Column
|
|
12
|
+
pn.extension('tabulator')
|
|
13
|
+
PANEL_AVAILABLE = True
|
|
14
|
+
except ImportError:
|
|
15
|
+
PANEL_AVAILABLE = False
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@register_renderer(OutputMode.HTML)
|
|
19
|
+
class HTMLRenderer(BaseRenderer):
|
|
20
|
+
"""Renderer for HTML output using Panel or simple HTML fallback"""
|
|
21
|
+
|
|
22
|
+
async def render(
|
|
23
|
+
self,
|
|
24
|
+
response: Any,
|
|
25
|
+
**kwargs,
|
|
26
|
+
) -> Tuple[Any, Optional[str]]:
|
|
27
|
+
"""
|
|
28
|
+
Render response as HTML, returning a primary content object and a wrapped HTML string.
|
|
29
|
+
"""
|
|
30
|
+
use_panel = kwargs.get('use_panel', True) and PANEL_AVAILABLE
|
|
31
|
+
|
|
32
|
+
if use_panel:
|
|
33
|
+
dashboard = self._render_with_panel(response, **kwargs)
|
|
34
|
+
html_string = self._panel_to_html(dashboard)
|
|
35
|
+
content = dashboard
|
|
36
|
+
wrapped = html_string
|
|
37
|
+
else:
|
|
38
|
+
html_string = self._render_simple_html(response, **kwargs)
|
|
39
|
+
content = html_string
|
|
40
|
+
wrapped = html_string
|
|
41
|
+
|
|
42
|
+
return content, wrapped
|
|
43
|
+
|
|
44
|
+
def _render_with_panel(self, response: Any, **kwargs) -> Any:
|
|
45
|
+
"""
|
|
46
|
+
Format output as an interactive Panel dashboard.
|
|
47
|
+
"""
|
|
48
|
+
components = self._build_panel_components(response, **kwargs)
|
|
49
|
+
return Column(*components, sizing_mode='stretch_width', styles={'background': '#ffffff', 'padding': '20px'})
|
|
50
|
+
|
|
51
|
+
def _build_panel_components(self, response: Any, **kwargs) -> list:
|
|
52
|
+
show_metadata = kwargs.get('show_metadata', True)
|
|
53
|
+
show_sources = kwargs.get('show_sources', True)
|
|
54
|
+
show_tools = kwargs.get('show_tools', False)
|
|
55
|
+
components = []
|
|
56
|
+
|
|
57
|
+
if content := self._get_content(response):
|
|
58
|
+
components.extend([
|
|
59
|
+
pn.pane.HTML("<h2>🤖 Response</h2>"),
|
|
60
|
+
PanelMarkdown(
|
|
61
|
+
content, sizing_mode='stretch_width',
|
|
62
|
+
styles={'background': '#f0f8ff', 'padding': '20px', 'border-radius': '5px'}
|
|
63
|
+
)
|
|
64
|
+
])
|
|
65
|
+
if show_tools and hasattr(response, 'tool_calls') and response.tool_calls:
|
|
66
|
+
tools_df = self._create_tools_dataframe(response.tool_calls)
|
|
67
|
+
components.extend([
|
|
68
|
+
pn.pane.HTML("<h3>🔧 Tool Calls</h3>"),
|
|
69
|
+
pn.widgets.Tabulator(tools_df, sizing_mode='stretch_width', theme='modern', show_index=False)
|
|
70
|
+
])
|
|
71
|
+
if show_metadata:
|
|
72
|
+
metadata_html = self._create_metadata_panel(response)
|
|
73
|
+
components.extend([pn.pane.HTML("<h3>📊 Metadata</h3>"), pn.pane.HTML(metadata_html)])
|
|
74
|
+
if show_sources and hasattr(response, 'source_documents') and response.source_documents:
|
|
75
|
+
sources_df = self._create_sources_dataframe(response.source_documents)
|
|
76
|
+
components.extend([
|
|
77
|
+
pn.pane.HTML("<h3>📄 Sources</h3>"),
|
|
78
|
+
pn.widgets.Tabulator(sources_df, sizing_mode='stretch_width', theme='modern', show_index=False)
|
|
79
|
+
])
|
|
80
|
+
return components
|
|
81
|
+
|
|
82
|
+
def _panel_to_html(self, dashboard: Any) -> str:
|
|
83
|
+
"""Convert Panel dashboard to an HTML string."""
|
|
84
|
+
with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False) as tmp:
|
|
85
|
+
tmp_path = tmp.name
|
|
86
|
+
try:
|
|
87
|
+
dashboard.save(tmp_path, embed=True)
|
|
88
|
+
with open(tmp_path, 'r', encoding='utf-8') as f:
|
|
89
|
+
return f.read()
|
|
90
|
+
finally:
|
|
91
|
+
if os.path.exists(tmp_path):
|
|
92
|
+
os.unlink(tmp_path)
|
|
93
|
+
|
|
94
|
+
def _create_tools_dataframe(self, tool_calls: List[Any]):
|
|
95
|
+
import pandas as pd
|
|
96
|
+
return pd.DataFrame([
|
|
97
|
+
{'#': idx, 'Tool Name': getattr(tool, 'name', 'Unknown'), 'Status': getattr(tool, 'status', 'completed')}
|
|
98
|
+
for idx, tool in enumerate(tool_calls, 1)
|
|
99
|
+
])
|
|
100
|
+
|
|
101
|
+
def _create_sources_dataframe(self, sources: List[Any]):
|
|
102
|
+
import pandas as pd
|
|
103
|
+
return pd.DataFrame([
|
|
104
|
+
{
|
|
105
|
+
'#': idx,
|
|
106
|
+
'Source': getattr(source, 'source', source.get('source', 'Unknown')),
|
|
107
|
+
'Score': f"{getattr(source, 'score', source.get('score', 'N/A')):.4f}"
|
|
108
|
+
}
|
|
109
|
+
for idx, source in enumerate(sources, 1)
|
|
110
|
+
])
|
|
111
|
+
|
|
112
|
+
def _create_metadata_panel(self, response: Any) -> str:
|
|
113
|
+
items = []
|
|
114
|
+
if hasattr(response, 'model'):
|
|
115
|
+
items.append(f"<div class='metadata-item'><span class='key'>Model:</span> <span class='value'>{response.model}</span></div>")
|
|
116
|
+
return f"<div class='metadata-container'>{''.join(items)}</div>"
|
|
117
|
+
|
|
118
|
+
def _render_simple_html(self, response: Any, **kwargs) -> str:
|
|
119
|
+
"""Format output as a simple HTML string."""
|
|
120
|
+
html_parts = [self._get_html_header()]
|
|
121
|
+
if content := self._get_content(response):
|
|
122
|
+
html_parts.append(f"<div class='ap-response-container'><h2>🤖 Response</h2><div class='ap-content'>{self._markdown_to_html(content)}</div></div>")
|
|
123
|
+
if kwargs.get('show_tools', False) and hasattr(response, 'tool_calls') and response.tool_calls:
|
|
124
|
+
html_parts.append(f"<div class='ap-section'><h3>🔧 Tool Calls</h3>{self._create_tools_html(response.tool_calls)}</div>")
|
|
125
|
+
html_parts.append('</body></html>')
|
|
126
|
+
return '\n'.join(html_parts)
|
|
127
|
+
|
|
128
|
+
def _get_html_header(self) -> str:
|
|
129
|
+
return '''
|
|
130
|
+
<!DOCTYPE html><html><head><title>AI Response</title>
|
|
131
|
+
<style>.ap-html-wrapper { font-family: sans-serif; } .ap-response-container { background: #f0f8ff; }</style>
|
|
132
|
+
</head><body class="ap-html-wrapper">
|
|
133
|
+
'''
|
|
134
|
+
|
|
135
|
+
def _markdown_to_html(self, content: str) -> str:
|
|
136
|
+
try:
|
|
137
|
+
import markdown
|
|
138
|
+
return markdown.markdown(content, extensions=['fenced_code', 'tables', 'nl2br'])
|
|
139
|
+
except ImportError:
|
|
140
|
+
return f"<p>{content.replace(chr(10), '<br>')}</p>"
|
|
141
|
+
|
|
142
|
+
def _create_tools_html(self, tool_calls: List[Any]) -> str:
|
|
143
|
+
rows = "".join(
|
|
144
|
+
f"<tr><td><strong>{idx}</strong></td><td>{getattr(tool, 'name', 'Unknown')}</td><td><span class='badge'>completed</span></td></tr>"
|
|
145
|
+
for idx, tool in enumerate(tool_calls, 1)
|
|
146
|
+
)
|
|
147
|
+
return f"<table><thead><tr><th>#</th><th>Tool Name</th><th>Status</th></tr></thead><tbody>{rows}</tbody></table>"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import mimetypes
|
|
2
|
+
from typing import Any, Tuple
|
|
3
|
+
|
|
4
|
+
from jinja2 import Environment
|
|
5
|
+
|
|
6
|
+
from ...models.outputs import OutputMode
|
|
7
|
+
from . import register_renderer
|
|
8
|
+
from .base import BaseRenderer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@register_renderer(OutputMode.JINJA2)
|
|
12
|
+
class Jinja2Renderer(BaseRenderer):
|
|
13
|
+
"""
|
|
14
|
+
Renders the output using a Jinja2 template.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
async def render(self, data: Any, **kwargs: Any) -> Tuple[str, str]:
|
|
18
|
+
"""
|
|
19
|
+
Renders data using a Jinja2 template asynchronously.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
data: The data to render.
|
|
23
|
+
**kwargs: Must contain 'env' (a Jinja2 Environment) and 'template' (the template name).
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
A tuple containing the rendered content and the guessed MIME type.
|
|
27
|
+
"""
|
|
28
|
+
env: Environment = kwargs.get("env")
|
|
29
|
+
if not env:
|
|
30
|
+
raise ValueError("Jinja2 environment not provided in kwargs.")
|
|
31
|
+
|
|
32
|
+
template_name: str = kwargs.get("template")
|
|
33
|
+
if not template_name:
|
|
34
|
+
raise ValueError("Jinja2 template name not provided in kwargs.")
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
template = env.get_template(template_name)
|
|
38
|
+
except Exception as e:
|
|
39
|
+
raise ValueError(
|
|
40
|
+
f"Failed to load Jinja2 template '{template_name}': {e}"
|
|
41
|
+
) from e
|
|
42
|
+
|
|
43
|
+
content_type = mimetypes.guess_type(template_name)[0] or "text/plain"
|
|
44
|
+
|
|
45
|
+
rendered_content = await template.render_async(**data)
|
|
46
|
+
return rendered_content, content_type
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from typing import Any, Tuple, Optional
|
|
2
|
+
from . import register_renderer
|
|
3
|
+
from .base import BaseRenderer
|
|
4
|
+
from ...models.outputs import OutputMode
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@register_renderer(OutputMode.JSON)
|
|
8
|
+
class JSONRenderer(BaseRenderer):
|
|
9
|
+
"""
|
|
10
|
+
Renderer for JSON output.
|
|
11
|
+
Handles PandasAgentResponse, DataFrames, Pydantic models, and generic content.
|
|
12
|
+
Adapts output format to Terminal (Rich), HTML (Pygments), and Jupyter (Widgets).
|
|
13
|
+
"""
|
|
14
|
+
async def render(
|
|
15
|
+
self,
|
|
16
|
+
response: Any,
|
|
17
|
+
environment: str = 'default',
|
|
18
|
+
**kwargs,
|
|
19
|
+
) -> Tuple[Any, Optional[Any]]:
|
|
20
|
+
"""
|
|
21
|
+
Render response as JSON.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Tuple[str, Any]: (json_string, wrapped_content)
|
|
25
|
+
"""
|
|
26
|
+
indent = kwargs.get('indent')
|
|
27
|
+
output_format = kwargs.get('output_format', environment)
|
|
28
|
+
|
|
29
|
+
# 1. Extract Data
|
|
30
|
+
data = self._extract_data(response)
|
|
31
|
+
|
|
32
|
+
# 2. Serialize to content string
|
|
33
|
+
json_string = self._serialize(data, indent=indent)
|
|
34
|
+
|
|
35
|
+
# 3. Wrap content based on environment
|
|
36
|
+
wrapped_output = self._wrap_output(json_string, data, output_format)
|
|
37
|
+
|
|
38
|
+
return json_string, wrapped_output
|
|
39
|
+
|
|
40
|
+
def _wrap_output(self, json_string: str, data: Any, environment: str) -> Any:
|
|
41
|
+
"""
|
|
42
|
+
Wrap the JSON string into an environment-specific container.
|
|
43
|
+
"""
|
|
44
|
+
if environment == 'terminal':
|
|
45
|
+
try:
|
|
46
|
+
from rich.panel import Panel
|
|
47
|
+
from rich.syntax import Syntax
|
|
48
|
+
from rich.json import JSON as RichJSON
|
|
49
|
+
|
|
50
|
+
# Use Rich's native JSON rendering if possible for better formatting
|
|
51
|
+
return Panel(
|
|
52
|
+
RichJSON(json_string),
|
|
53
|
+
title="JSON Output",
|
|
54
|
+
border_style="green"
|
|
55
|
+
)
|
|
56
|
+
except ImportError:
|
|
57
|
+
return json_string
|
|
58
|
+
|
|
59
|
+
elif environment in {'jupyter', 'notebook'}:
|
|
60
|
+
try:
|
|
61
|
+
# For Jupyter, we try to return a Widget or specialized display object
|
|
62
|
+
# Method A: ipywidgets (Interactive)
|
|
63
|
+
from ipywidgets import HTML
|
|
64
|
+
|
|
65
|
+
# Create formatted HTML for the JSON
|
|
66
|
+
from pygments import highlight
|
|
67
|
+
from pygments.lexers import JsonLexer
|
|
68
|
+
from pygments.formatters import HtmlFormatter
|
|
69
|
+
|
|
70
|
+
formatter = HtmlFormatter(style='colorful', noclasses=True)
|
|
71
|
+
highlighted_html = highlight(json_string, JsonLexer(), formatter)
|
|
72
|
+
|
|
73
|
+
# Wrap in a widget
|
|
74
|
+
widget = HTML(
|
|
75
|
+
value=f'<div style="max-height: 500px; overflow-y: auto; background-color: #f8f8f8; padding: 10px;">{highlighted_html}</div>'
|
|
76
|
+
)
|
|
77
|
+
return widget
|
|
78
|
+
|
|
79
|
+
except ImportError:
|
|
80
|
+
# Fallback to HTML representation if widgets not available
|
|
81
|
+
return self._wrap_html(json_string)
|
|
82
|
+
|
|
83
|
+
elif environment == 'html':
|
|
84
|
+
return self._wrap_html(json_string)
|
|
85
|
+
|
|
86
|
+
# Default / Text
|
|
87
|
+
return json_string
|