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,306 @@
|
|
|
1
|
+
"""YFinance tool for retrieving market data via Yahoo Finance."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import asyncio
|
|
4
|
+
from datetime import datetime, timezone
|
|
5
|
+
from typing import Any, Dict, Optional, Literal, Union
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pandas as pd
|
|
8
|
+
import yfinance as yf
|
|
9
|
+
from pydantic import Field, field_validator
|
|
10
|
+
|
|
11
|
+
from .abstract import AbstractTool, AbstractToolArgsSchema, ToolResult
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class YFinanceArgs(AbstractToolArgsSchema):
|
|
15
|
+
"""Argument schema for :class:`YFinanceTool`."""
|
|
16
|
+
|
|
17
|
+
ticker: str = Field(
|
|
18
|
+
...,
|
|
19
|
+
description="Ticker symbol to query (for example: AAPL, MSFT, TSLA).",
|
|
20
|
+
min_length=1,
|
|
21
|
+
max_length=32,
|
|
22
|
+
)
|
|
23
|
+
action: Literal["quote", "info", "history", "financials"] = Field(
|
|
24
|
+
"quote",
|
|
25
|
+
description=(
|
|
26
|
+
"Type of data to retrieve. "
|
|
27
|
+
"'quote' returns the latest market quote, 'info' returns company details, "
|
|
28
|
+
"'history' returns historical price data, and 'financials' returns financial statements."
|
|
29
|
+
),
|
|
30
|
+
)
|
|
31
|
+
period: Optional[str] = Field(
|
|
32
|
+
"1mo",
|
|
33
|
+
description=(
|
|
34
|
+
"Period for historical data (used when action='history'). Examples: '1d', '5d', '1mo', "
|
|
35
|
+
"'3mo', '6mo', '1y', '5y', '10y', 'ytd', 'max'."
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
interval: Optional[str] = Field(
|
|
39
|
+
"1d",
|
|
40
|
+
description=(
|
|
41
|
+
"Data interval for historical data (used when action='history'). Examples: '1m', '5m', '15m', "
|
|
42
|
+
"'1h', '1d', '1wk', '1mo'."
|
|
43
|
+
),
|
|
44
|
+
)
|
|
45
|
+
start: Optional[Union[datetime, str]] = Field(
|
|
46
|
+
None,
|
|
47
|
+
description=(
|
|
48
|
+
"Optional start date for historical data. Accepts ISO formatted strings or datetime objects."
|
|
49
|
+
),
|
|
50
|
+
)
|
|
51
|
+
end: Optional[Union[datetime, str]] = Field(
|
|
52
|
+
None,
|
|
53
|
+
description=(
|
|
54
|
+
"Optional end date for historical data. Accepts ISO formatted strings or datetime objects."
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
auto_adjust: bool = Field(
|
|
58
|
+
True,
|
|
59
|
+
description="Adjust historical data for dividends and splits (used when action='history').",
|
|
60
|
+
)
|
|
61
|
+
include_actions: bool = Field(
|
|
62
|
+
False,
|
|
63
|
+
description="Include dividends and splits columns in historical results (action='history').",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@field_validator("ticker")
|
|
67
|
+
@classmethod
|
|
68
|
+
def normalize_ticker(cls, value: str) -> str:
|
|
69
|
+
if (ticker := value.strip().upper()):
|
|
70
|
+
return ticker
|
|
71
|
+
raise ValueError("Ticker symbol cannot be empty")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class YFinanceTool(AbstractTool):
|
|
76
|
+
"""Retrieve quotes, company information, and financial statements via Yahoo Finance."""
|
|
77
|
+
|
|
78
|
+
name = "yfinance_tool"
|
|
79
|
+
description = (
|
|
80
|
+
"Access Yahoo Finance market data including latest quotes, company information, "
|
|
81
|
+
"historical prices, and financial statements for a given ticker symbol."
|
|
82
|
+
)
|
|
83
|
+
args_schema = YFinanceArgs
|
|
84
|
+
|
|
85
|
+
async def _execute(self, **kwargs: Any) -> ToolResult:
|
|
86
|
+
args = self.args_schema(**kwargs)
|
|
87
|
+
loop = asyncio.get_running_loop()
|
|
88
|
+
return await loop.run_in_executor(None, self._run, args)
|
|
89
|
+
|
|
90
|
+
def _run(self, args: YFinanceArgs) -> ToolResult:
|
|
91
|
+
ticker = yf.Ticker(args.ticker)
|
|
92
|
+
action = args.action
|
|
93
|
+
|
|
94
|
+
retrieved_at = datetime.now(tz=timezone.utc).isoformat() + "Z"
|
|
95
|
+
|
|
96
|
+
if action == "quote":
|
|
97
|
+
payload = self._get_quote(ticker, args, retrieved_at)
|
|
98
|
+
elif action == "info":
|
|
99
|
+
payload = self._get_info(ticker, args, retrieved_at)
|
|
100
|
+
elif action == "history":
|
|
101
|
+
payload = self._get_history(ticker, args, retrieved_at)
|
|
102
|
+
elif action == "financials":
|
|
103
|
+
payload = self._get_financials(ticker, args, retrieved_at)
|
|
104
|
+
else:
|
|
105
|
+
raise ValueError(f"Unsupported action: {action}")
|
|
106
|
+
|
|
107
|
+
return ToolResult(
|
|
108
|
+
status="success",
|
|
109
|
+
result=payload,
|
|
110
|
+
metadata={
|
|
111
|
+
"symbol": args.ticker,
|
|
112
|
+
"action": action,
|
|
113
|
+
"source": "yfinance",
|
|
114
|
+
"retrieved_at": retrieved_at,
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def _get_quote(
|
|
119
|
+
self, ticker: yf.Ticker, args: YFinanceArgs, retrieved_at: str
|
|
120
|
+
) -> Dict[str, Any]:
|
|
121
|
+
fast_info: Dict[str, Any] = {}
|
|
122
|
+
info: Dict[str, Any] = {}
|
|
123
|
+
|
|
124
|
+
try:
|
|
125
|
+
fast_info = dict(getattr(ticker, "fast_info", {}) or {})
|
|
126
|
+
except Exception as exc: # pragma: no cover - defensive
|
|
127
|
+
self.logger.warning("Unable to retrieve fast_info for %s: %s", args.ticker, exc)
|
|
128
|
+
|
|
129
|
+
try:
|
|
130
|
+
info = ticker.get_info() or {}
|
|
131
|
+
except Exception as exc: # pragma: no cover - defensive
|
|
132
|
+
self.logger.warning("Unable to retrieve info for %s: %s", args.ticker, exc)
|
|
133
|
+
|
|
134
|
+
def _extract_price() -> Optional[float]:
|
|
135
|
+
candidates = [
|
|
136
|
+
fast_info.get("lastPrice"),
|
|
137
|
+
fast_info.get("last_price"),
|
|
138
|
+
fast_info.get("regularMarketPrice"),
|
|
139
|
+
info.get("regularMarketPrice"),
|
|
140
|
+
]
|
|
141
|
+
for candidate in candidates:
|
|
142
|
+
if candidate is not None:
|
|
143
|
+
return self._to_native_number(candidate)
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
summary = {
|
|
147
|
+
"last_price": _extract_price(),
|
|
148
|
+
"currency": fast_info.get("currency") or info.get("currency"),
|
|
149
|
+
"previous_close": self._to_native_number(
|
|
150
|
+
fast_info.get("previousClose") or fast_info.get("previous_close") or info.get("previousClose")
|
|
151
|
+
),
|
|
152
|
+
"open": self._to_native_number(fast_info.get("open") or info.get("open")),
|
|
153
|
+
"day_range": {
|
|
154
|
+
"low": self._to_native_number(
|
|
155
|
+
fast_info.get("dayLow") or fast_info.get("day_low") or info.get("dayLow")
|
|
156
|
+
),
|
|
157
|
+
"high": self._to_native_number(
|
|
158
|
+
fast_info.get("dayHigh") or fast_info.get("day_high") or info.get("dayHigh")
|
|
159
|
+
),
|
|
160
|
+
},
|
|
161
|
+
"volume": self._to_native_number(fast_info.get("volume") or info.get("volume")),
|
|
162
|
+
"market_cap": self._to_native_number(
|
|
163
|
+
fast_info.get("marketCap") or fast_info.get("market_cap") or info.get("marketCap")
|
|
164
|
+
),
|
|
165
|
+
"exchange": info.get("exchange") or info.get("fullExchangeName"),
|
|
166
|
+
"timestamp": datetime.utcnow().isoformat() + "Z",
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
"ticker": args.ticker,
|
|
171
|
+
"retrieved_at": retrieved_at,
|
|
172
|
+
"quote": summary,
|
|
173
|
+
"fast_info": self._clean_nested(fast_info),
|
|
174
|
+
"info_excerpt": {
|
|
175
|
+
k: info.get(k)
|
|
176
|
+
for k in ("longName", "shortName", "quoteType", "sector", "industry")
|
|
177
|
+
if k in info
|
|
178
|
+
},
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
def _get_info(
|
|
182
|
+
self, ticker: yf.Ticker, args: YFinanceArgs, retrieved_at: str
|
|
183
|
+
) -> Dict[str, Any]:
|
|
184
|
+
try:
|
|
185
|
+
info = ticker.get_info() or {}
|
|
186
|
+
except Exception as exc:
|
|
187
|
+
raise ValueError(f"Unable to retrieve company info for {args.ticker}: {exc}") from exc
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
"ticker": args.ticker,
|
|
191
|
+
"retrieved_at": retrieved_at,
|
|
192
|
+
"info": self._clean_nested(info),
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
def _get_history(
|
|
196
|
+
self, ticker: yf.Ticker, args: YFinanceArgs, retrieved_at: str
|
|
197
|
+
) -> Dict[str, Any]:
|
|
198
|
+
history_df = ticker.history(
|
|
199
|
+
period=args.period,
|
|
200
|
+
interval=args.interval,
|
|
201
|
+
start=args.start,
|
|
202
|
+
end=args.end,
|
|
203
|
+
auto_adjust=args.auto_adjust,
|
|
204
|
+
actions=args.include_actions,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
records = []
|
|
208
|
+
if not history_df.empty:
|
|
209
|
+
history_df = history_df.reset_index()
|
|
210
|
+
for row in history_df.to_dict(orient="records"):
|
|
211
|
+
cleaned_row = {
|
|
212
|
+
key: (
|
|
213
|
+
value.isoformat()
|
|
214
|
+
if isinstance(value, (pd.Timestamp, datetime))
|
|
215
|
+
else self._clean_value(value)
|
|
216
|
+
)
|
|
217
|
+
for key, value in row.items()
|
|
218
|
+
}
|
|
219
|
+
records.append(cleaned_row)
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
"ticker": args.ticker,
|
|
223
|
+
"retrieved_at": retrieved_at,
|
|
224
|
+
"parameters": {
|
|
225
|
+
"period": args.period,
|
|
226
|
+
"interval": args.interval,
|
|
227
|
+
"start": self._format_datetime(args.start),
|
|
228
|
+
"end": self._format_datetime(args.end),
|
|
229
|
+
"auto_adjust": args.auto_adjust,
|
|
230
|
+
"include_actions": args.include_actions,
|
|
231
|
+
},
|
|
232
|
+
"records": records,
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
def _get_financials(
|
|
236
|
+
self, ticker: yf.Ticker, args: YFinanceArgs, retrieved_at: str
|
|
237
|
+
) -> Dict[str, Any]:
|
|
238
|
+
datasets = {
|
|
239
|
+
"financials": getattr(ticker, "financials", None),
|
|
240
|
+
"quarterly_financials": getattr(ticker, "quarterly_financials", None),
|
|
241
|
+
"balance_sheet": getattr(ticker, "balance_sheet", None),
|
|
242
|
+
"quarterly_balance_sheet": getattr(ticker, "quarterly_balance_sheet", None),
|
|
243
|
+
"cashflow": getattr(ticker, "cashflow", None),
|
|
244
|
+
"quarterly_cashflow": getattr(ticker, "quarterly_cashflow", None),
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
serialized = {
|
|
248
|
+
name: (
|
|
249
|
+
self._serialize_dataframe(df)
|
|
250
|
+
if df is not None and not df.empty
|
|
251
|
+
else {}
|
|
252
|
+
)
|
|
253
|
+
for name, df in datasets.items()
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
"ticker": args.ticker,
|
|
258
|
+
"retrieved_at": retrieved_at,
|
|
259
|
+
"financials": serialized,
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@staticmethod
|
|
263
|
+
def _format_datetime(value: Optional[Union[datetime, str]]) -> Optional[str]:
|
|
264
|
+
if value is None:
|
|
265
|
+
return None
|
|
266
|
+
return value.isoformat() if isinstance(value, datetime) else str(value)
|
|
267
|
+
|
|
268
|
+
@staticmethod
|
|
269
|
+
def _to_native_number(value: Any) -> Optional[float]:
|
|
270
|
+
if value is None:
|
|
271
|
+
return None
|
|
272
|
+
if isinstance(value, (int, float)):
|
|
273
|
+
return float(value)
|
|
274
|
+
if isinstance(value, np.generic):
|
|
275
|
+
return float(value.item())
|
|
276
|
+
try:
|
|
277
|
+
return float(value)
|
|
278
|
+
except (TypeError, ValueError):
|
|
279
|
+
return None
|
|
280
|
+
|
|
281
|
+
def _clean_value(self, value: Any) -> Any:
|
|
282
|
+
if isinstance(value, np.generic):
|
|
283
|
+
return value.item()
|
|
284
|
+
if isinstance(value, (pd.Timestamp, datetime)):
|
|
285
|
+
return value.isoformat()
|
|
286
|
+
if isinstance(value, (bytes, bytearray)):
|
|
287
|
+
return value.decode("utf-8", errors="ignore")
|
|
288
|
+
if isinstance(value, (list, tuple)):
|
|
289
|
+
return [self._clean_value(item) for item in value]
|
|
290
|
+
if isinstance(value, dict):
|
|
291
|
+
return {str(k): self._clean_value(v) for k, v in value.items()}
|
|
292
|
+
return value
|
|
293
|
+
|
|
294
|
+
def _clean_nested(self, data: Dict[str, Any]) -> Dict[str, Any]:
|
|
295
|
+
return {str(k): self._clean_value(v) for k, v in data.items()}
|
|
296
|
+
|
|
297
|
+
def _serialize_dataframe(self, df: pd.DataFrame) -> Dict[str, Dict[str, Any]]:
|
|
298
|
+
cleaned_df = df.copy()
|
|
299
|
+
cleaned_df.index = cleaned_df.index.map(self._clean_value)
|
|
300
|
+
cleaned_df.columns = [self._clean_value(col) for col in cleaned_df.columns]
|
|
301
|
+
cleaned_df = cleaned_df.applymap(self._clean_value)
|
|
302
|
+
result: Dict[str, Dict[str, Any]] = {
|
|
303
|
+
str(column): {str(idx): val for idx, val in values.items()}
|
|
304
|
+
for column, values in cleaned_df.to_dict().items()
|
|
305
|
+
}
|
|
306
|
+
return result
|
parrot/tools/zipcode.py
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ZipcodeAPI Toolkit - A unified toolkit for zipcode operations.
|
|
3
|
+
"""
|
|
4
|
+
from typing import List, Dict, Any, Optional, Union
|
|
5
|
+
import httpx
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
from navconfig import config
|
|
8
|
+
from .toolkit import AbstractToolkit
|
|
9
|
+
from .decorators import tool_schema
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Input schemas for different operations
|
|
13
|
+
class BasicZipcodeInput(BaseModel):
|
|
14
|
+
"""Basic input schema for zipcode operations."""
|
|
15
|
+
zipcode: Union[str, int] = Field(description="The zipcode")
|
|
16
|
+
unit: Optional[str] = Field(description="Unit for coordinates (degrees, radians)", default="degrees")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ZipcodeDistanceInput(BaseModel):
|
|
20
|
+
"""Input schema for zipcode distance calculation."""
|
|
21
|
+
zipcode1: Union[str, int] = Field(description="The first zipcode")
|
|
22
|
+
zipcode2: Union[str, int] = Field(description="The second zipcode")
|
|
23
|
+
unit: Optional[str] = Field(description="Unit for coordinates (degrees, radians)", default="degrees")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ZipcodeRadiusInput(BaseModel):
|
|
27
|
+
"""Input schema for zipcode radius search."""
|
|
28
|
+
zipcode: Union[str, int] = Field(description="The center zipcode")
|
|
29
|
+
radius: int = Field(description="The radius in miles", default=5)
|
|
30
|
+
unit: Optional[str] = Field(description="Unit for coordinates (degrees, radians)", default="degrees")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class CityToZipcodesInput(BaseModel):
|
|
34
|
+
"""Input schema for city to zipcodes lookup."""
|
|
35
|
+
city: str = Field(description="The city name")
|
|
36
|
+
state: str = Field(description="The state abbreviation (e.g., 'FL', 'CA')")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ZipcodeAPIToolkit(AbstractToolkit):
|
|
40
|
+
"""
|
|
41
|
+
Toolkit for interacting with ZipcodeAPI service.
|
|
42
|
+
|
|
43
|
+
Provides methods for:
|
|
44
|
+
- Getting zipcode location information
|
|
45
|
+
- Calculating distance between zipcodes
|
|
46
|
+
- Finding zipcodes within a radius
|
|
47
|
+
- Finding zipcodes for a city/state
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, api_key: Optional[str] = None, **kwargs):
|
|
51
|
+
"""
|
|
52
|
+
Initialize the ZipcodeAPI toolkit.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
api_key: ZipcodeAPI key. If None, will use config.get('ZIPCODE_API_KEY')
|
|
56
|
+
**kwargs: Additional toolkit configuration
|
|
57
|
+
"""
|
|
58
|
+
super().__init__(**kwargs)
|
|
59
|
+
self.api_key = api_key or config.get('ZIPCODE_API_KEY')
|
|
60
|
+
if not self.api_key:
|
|
61
|
+
raise ValueError(
|
|
62
|
+
"ZipcodeAPI key is required. Set ZIPCODE_API_KEY in config or pass api_key parameter."
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@tool_schema(BasicZipcodeInput)
|
|
66
|
+
async def get_zipcode_location(self, zipcode: Union[str, int], unit: str = "degrees") -> Dict[str, Any]:
|
|
67
|
+
"""
|
|
68
|
+
Get geographical information for a zipcode including city, state, latitude, longitude, and timezone.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
zipcode: The zipcode to lookup
|
|
72
|
+
unit: Unit for coordinates (degrees, radians)
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Dictionary with location information
|
|
76
|
+
"""
|
|
77
|
+
url = f"https://www.zipcodeapi.com/rest/{self.api_key}/info.json/{zipcode}/{unit}"
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
async with httpx.AsyncClient() as client:
|
|
81
|
+
response = await client.get(url)
|
|
82
|
+
response.raise_for_status()
|
|
83
|
+
return response.json()
|
|
84
|
+
except httpx.HTTPStatusError as e:
|
|
85
|
+
raise ValueError(f"Error fetching zipcode location for {zipcode}: {e}") from e
|
|
86
|
+
|
|
87
|
+
@tool_schema(ZipcodeDistanceInput)
|
|
88
|
+
async def calculate_zipcode_distance(
|
|
89
|
+
self,
|
|
90
|
+
zipcode1: Union[str, int],
|
|
91
|
+
zipcode2: Union[str, int],
|
|
92
|
+
unit: str = "mile"
|
|
93
|
+
) -> Dict[str, Any]:
|
|
94
|
+
"""
|
|
95
|
+
Calculate the distance between two zipcodes.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
zipcode1: First zipcode
|
|
99
|
+
zipcode2: Second zipcode
|
|
100
|
+
unit: Unit of distance (mile, km)
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Dictionary with distance information
|
|
104
|
+
"""
|
|
105
|
+
url = f"https://www.zipcodeapi.com/rest/{self.api_key}/distance.json/{zipcode1}/{zipcode2}/{unit}"
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
async with httpx.AsyncClient() as client:
|
|
109
|
+
response = await client.get(url)
|
|
110
|
+
response.raise_for_status()
|
|
111
|
+
return response.json()
|
|
112
|
+
except httpx.HTTPStatusError as e:
|
|
113
|
+
raise ValueError(f"Error calculating distance between {zipcode1} and {zipcode2}: {e}") from e
|
|
114
|
+
|
|
115
|
+
@tool_schema(ZipcodeRadiusInput)
|
|
116
|
+
async def find_zipcodes_in_radius(
|
|
117
|
+
self,
|
|
118
|
+
zipcode: Union[str, int],
|
|
119
|
+
radius: int = 5,
|
|
120
|
+
unit: str = "mile"
|
|
121
|
+
) -> Dict[str, Any]:
|
|
122
|
+
"""
|
|
123
|
+
Find all zipcodes within a given radius of a center zipcode.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
zipcode: Center zipcode
|
|
127
|
+
radius: Search radius
|
|
128
|
+
unit: Unit of distance (mile, km)
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Dictionary with list of zipcodes in radius
|
|
132
|
+
"""
|
|
133
|
+
url = f"https://www.zipcodeapi.com/rest/{self.api_key}/radius.json/{zipcode}/{radius}/{unit}"
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
async with httpx.AsyncClient() as client:
|
|
137
|
+
response = await client.get(url)
|
|
138
|
+
response.raise_for_status()
|
|
139
|
+
return response.json()
|
|
140
|
+
except httpx.HTTPStatusError as e:
|
|
141
|
+
raise ValueError(f"Error finding zipcodes within {radius} {unit}s of {zipcode}: {e}") from e
|
|
142
|
+
|
|
143
|
+
@tool_schema(CityToZipcodesInput)
|
|
144
|
+
async def get_city_zipcodes(self, city: str, state: str) -> Dict[str, Any]:
|
|
145
|
+
"""
|
|
146
|
+
Get all zipcodes for a given city and state.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
city: City name
|
|
150
|
+
state: State abbreviation (e.g., 'FL', 'CA')
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Dictionary with list of zipcodes for the city
|
|
154
|
+
"""
|
|
155
|
+
url = f"https://www.zipcodeapi.com/rest/{self.api_key}/city-zips.json/{city}/{state}"
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
async with httpx.AsyncClient() as client:
|
|
159
|
+
response = await client.get(url)
|
|
160
|
+
response.raise_for_status()
|
|
161
|
+
return response.json()
|
|
162
|
+
except httpx.HTTPStatusError as e:
|
|
163
|
+
raise ValueError(f"Error getting zipcodes for {city}, {state}: {e}") from e
|
|
164
|
+
|
|
165
|
+
async def get_multiple_locations(
|
|
166
|
+
self,
|
|
167
|
+
zipcodes: List[Union[str, int]],
|
|
168
|
+
unit: str = "degrees"
|
|
169
|
+
) -> Dict[str, Any]:
|
|
170
|
+
"""
|
|
171
|
+
Get location information for multiple zipcodes.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
zipcodes: List of zipcodes to lookup
|
|
175
|
+
unit: Unit for coordinates
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
Dictionary mapping zipcodes to their location info
|
|
179
|
+
"""
|
|
180
|
+
results = {}
|
|
181
|
+
|
|
182
|
+
async with httpx.AsyncClient() as client:
|
|
183
|
+
for zipcode in zipcodes:
|
|
184
|
+
try:
|
|
185
|
+
url = f"https://www.zipcodeapi.com/rest/{self.api_key}/info.json/{zipcode}/{unit}"
|
|
186
|
+
response = await client.get(url)
|
|
187
|
+
response.raise_for_status()
|
|
188
|
+
results[str(zipcode)] = response.json()
|
|
189
|
+
except httpx.HTTPStatusError as e:
|
|
190
|
+
results[str(zipcode)] = {"error": f"Failed to fetch: {e}"}
|
|
191
|
+
|
|
192
|
+
return {"results": results}
|
|
193
|
+
|
|
194
|
+
async def validate_zipcode(self, zipcode: Union[str, int]) -> Dict[str, Any]:
|
|
195
|
+
"""
|
|
196
|
+
Validate if a zipcode exists and return basic info.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
zipcode: Zipcode to validate
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
Dictionary with validation result and basic info if valid
|
|
203
|
+
"""
|
|
204
|
+
try:
|
|
205
|
+
result = await self.get_zipcode_location(zipcode)
|
|
206
|
+
return {
|
|
207
|
+
"valid": True,
|
|
208
|
+
"zipcode": zipcode,
|
|
209
|
+
"city": result.get("city"),
|
|
210
|
+
"state": result.get("state")
|
|
211
|
+
}
|
|
212
|
+
except ValueError:
|
|
213
|
+
return {
|
|
214
|
+
"valid": False,
|
|
215
|
+
"zipcode": zipcode,
|
|
216
|
+
"error": "Invalid zipcode"
|
|
217
|
+
}
|
parrot/utils/__init__.py
ADDED
parrot/utils/helpers.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from typing import Any, Optional
|
|
2
|
+
import inspect
|
|
3
|
+
from aiohttp import web
|
|
4
|
+
|
|
5
|
+
class RequestContext:
|
|
6
|
+
"""RequestContext.
|
|
7
|
+
|
|
8
|
+
This class is a context manager for handling request-specific data.
|
|
9
|
+
It is designed to be used with the `async with` statement to ensure
|
|
10
|
+
proper setup and teardown of resources.
|
|
11
|
+
|
|
12
|
+
Attributes:
|
|
13
|
+
request (web.Request): The incoming web request.
|
|
14
|
+
app (Optional[Any]): An optional application context.
|
|
15
|
+
llm (Optional[Any]): An optional language model instance.
|
|
16
|
+
kwargs (dict): Additional keyword arguments for customization.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
request: web.Request = None,
|
|
22
|
+
app: Optional[Any] = None,
|
|
23
|
+
llm: Optional[Any] = None,
|
|
24
|
+
**kwargs
|
|
25
|
+
):
|
|
26
|
+
"""Initialize the RequestContext with the given parameters."""
|
|
27
|
+
self.request = request
|
|
28
|
+
self.app = app
|
|
29
|
+
self.llm = llm
|
|
30
|
+
self.kwargs = kwargs
|
|
31
|
+
|
|
32
|
+
async def __aenter__(self):
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
async def __aexit__(self, exc_type, exc_value, traceback):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class RequestBot:
|
|
40
|
+
"""RequestBot.
|
|
41
|
+
|
|
42
|
+
This class is a wrapper around the AbstractBot to provide request-specific context.
|
|
43
|
+
"""
|
|
44
|
+
def __init__(self, delegate: Any, context: RequestContext):
|
|
45
|
+
self.delegate = delegate
|
|
46
|
+
self.ctx = context
|
|
47
|
+
|
|
48
|
+
def __getattr__(self, name: str):
|
|
49
|
+
attr = getattr(self.delegate, name)
|
|
50
|
+
# If the attribute is a callable method (and not just a property)
|
|
51
|
+
if callable(attr):
|
|
52
|
+
# Check if the original method is async
|
|
53
|
+
if inspect.iscoroutinefunction(attr):
|
|
54
|
+
# Return a new ASYNC function that wraps the original
|
|
55
|
+
async def async_wrapper(*args, **kwargs):
|
|
56
|
+
# Inject the context into the call
|
|
57
|
+
if 'ctx' not in kwargs:
|
|
58
|
+
kwargs['ctx'] = self.ctx
|
|
59
|
+
# Await the original async method with the modified arguments
|
|
60
|
+
return await attr(*args, **kwargs)
|
|
61
|
+
return async_wrapper
|
|
62
|
+
else:
|
|
63
|
+
# Return a new SYNC function that wraps the original
|
|
64
|
+
def sync_wrapper(*args, **kwargs):
|
|
65
|
+
# Inject the context into the call
|
|
66
|
+
if 'ctx' not in kwargs:
|
|
67
|
+
kwargs['ctx'] = self.ctx
|
|
68
|
+
# Call the original sync method with the modified arguments
|
|
69
|
+
return attr(*args, **kwargs)
|
|
70
|
+
return sync_wrapper
|
|
71
|
+
else:
|
|
72
|
+
# If it's a simple attribute (e.g., self.delegate.name), return it directly
|
|
73
|
+
return attr
|