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,369 @@
|
|
|
1
|
+
from abc import abstractmethod
|
|
2
|
+
from typing import List, Dict, Any, Optional, Tuple
|
|
3
|
+
import asyncio
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from arangoasync import ArangoClient
|
|
7
|
+
from arangoasync.auth import Auth
|
|
8
|
+
import bm25s
|
|
9
|
+
|
|
10
|
+
# Assuming these are your existing imports
|
|
11
|
+
from .abstract import AbstractTool
|
|
12
|
+
from ..stores import Store # Your pgVector implementation
|
|
13
|
+
# You'll need: pip install bm25s rank-bm25 faiss-cpu aioarango
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class SearchResult:
|
|
18
|
+
"""Unified search result across different stores"""
|
|
19
|
+
content: str
|
|
20
|
+
metadata: Dict[str, Any]
|
|
21
|
+
score: float
|
|
22
|
+
source: str # 'pgvector', 'faiss', 'arango'
|
|
23
|
+
original_rank: int
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class StoreType(Enum):
|
|
27
|
+
PGVECTOR = "pgvector"
|
|
28
|
+
FAISS = "faiss"
|
|
29
|
+
ARANGO = "arango"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MultiStoreSearchTool(AbstractTool):
|
|
33
|
+
"""
|
|
34
|
+
Multi-store search tool with BM25 reranking.
|
|
35
|
+
|
|
36
|
+
Performs parallel searches across pgVector, FAISS, and ArangoDB,
|
|
37
|
+
then applies BM25S for intelligent reranking and priority selection.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(
|
|
41
|
+
self,
|
|
42
|
+
pgvector_store: Store,
|
|
43
|
+
faiss_store: Any, # Your FAISS wrapper
|
|
44
|
+
arango_config: Dict[str, Any],
|
|
45
|
+
k: int = 10,
|
|
46
|
+
k_per_store: int = 20, # Fetch more initially for better reranking
|
|
47
|
+
bm25_weights: Optional[Dict[str, float]] = None,
|
|
48
|
+
enable_stores: Optional[List[StoreType]] = None,
|
|
49
|
+
**kwargs
|
|
50
|
+
):
|
|
51
|
+
super().__init__(**kwargs)
|
|
52
|
+
self.pgvector_store = pgvector_store
|
|
53
|
+
self.faiss_store = faiss_store
|
|
54
|
+
self.arango_config = arango_config
|
|
55
|
+
self.k = k
|
|
56
|
+
self.k_per_store = k_per_store
|
|
57
|
+
|
|
58
|
+
# Store-specific weights for final scoring
|
|
59
|
+
self.bm25_weights = bm25_weights or {
|
|
60
|
+
'pgvector': 1.0,
|
|
61
|
+
'faiss': 0.9,
|
|
62
|
+
'arango': 0.95
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
# Allow selective enabling of stores
|
|
66
|
+
self.enabled_stores = enable_stores or [
|
|
67
|
+
StoreType.PGVECTOR,
|
|
68
|
+
StoreType.FAISS,
|
|
69
|
+
StoreType.ARANGO
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
self._arango_client = None
|
|
73
|
+
self._bm25 = None
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def name(self) -> str:
|
|
77
|
+
return "multi_store_search"
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def description(self) -> str:
|
|
81
|
+
return (
|
|
82
|
+
"Search across multiple vector stores (pgVector, FAISS, ArangoDB) "
|
|
83
|
+
"with BM25S reranking for optimal results"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
async def _search_pgvector(
|
|
87
|
+
self,
|
|
88
|
+
query: str,
|
|
89
|
+
k: int
|
|
90
|
+
) -> List[SearchResult]:
|
|
91
|
+
"""Search pgVector store"""
|
|
92
|
+
try:
|
|
93
|
+
# Assuming your Store has an async search method
|
|
94
|
+
results = await self.pgvector_store.asearch(
|
|
95
|
+
query=query,
|
|
96
|
+
k=k
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
return [
|
|
100
|
+
SearchResult(
|
|
101
|
+
content=doc.page_content if hasattr(doc, 'page_content') else str(doc),
|
|
102
|
+
metadata=doc.metadata if hasattr(doc, 'metadata') else {},
|
|
103
|
+
score=score,
|
|
104
|
+
source='pgvector',
|
|
105
|
+
original_rank=idx
|
|
106
|
+
)
|
|
107
|
+
for idx, (doc, score) in enumerate(results)
|
|
108
|
+
]
|
|
109
|
+
except Exception as e:
|
|
110
|
+
print(f"PgVector search error: {e}")
|
|
111
|
+
return []
|
|
112
|
+
|
|
113
|
+
async def _search_faiss(
|
|
114
|
+
self,
|
|
115
|
+
query: str,
|
|
116
|
+
k: int
|
|
117
|
+
) -> List[SearchResult]:
|
|
118
|
+
"""Search FAISS store"""
|
|
119
|
+
try:
|
|
120
|
+
# Adapt to your FAISS implementation
|
|
121
|
+
results = await asyncio.to_thread(
|
|
122
|
+
self.faiss_store.similarity_search_with_score,
|
|
123
|
+
query,
|
|
124
|
+
k=k
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
return [
|
|
128
|
+
SearchResult(
|
|
129
|
+
content=doc.page_content if hasattr(doc, 'page_content') else str(doc),
|
|
130
|
+
metadata=doc.metadata if hasattr(doc, 'metadata') else {},
|
|
131
|
+
score=score,
|
|
132
|
+
source='faiss',
|
|
133
|
+
original_rank=idx
|
|
134
|
+
)
|
|
135
|
+
for idx, (doc, score) in enumerate(results)
|
|
136
|
+
]
|
|
137
|
+
except Exception as e:
|
|
138
|
+
print(f"FAISS search error: {e}")
|
|
139
|
+
return []
|
|
140
|
+
|
|
141
|
+
async def _search_arango(
|
|
142
|
+
self,
|
|
143
|
+
query: str,
|
|
144
|
+
k: int
|
|
145
|
+
) -> List[SearchResult]:
|
|
146
|
+
"""Search ArangoDB using AQL with fulltext or vector search"""
|
|
147
|
+
try:
|
|
148
|
+
if not self._arango_client:
|
|
149
|
+
self._arango_client = ArangoClient(
|
|
150
|
+
hosts=self.arango_config.get('hosts', 'http://localhost:8529')
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
db = await self._arango_client.db(
|
|
154
|
+
self.arango_config['database'],
|
|
155
|
+
username=self.arango_config['username'],
|
|
156
|
+
password=self.arango_config['password']
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# AQL query - adapt based on your schema
|
|
160
|
+
collection = self.arango_config.get('collection', 'documents')
|
|
161
|
+
|
|
162
|
+
# Example with fulltext search - adjust to your needs
|
|
163
|
+
aql = f"""
|
|
164
|
+
FOR doc IN FULLTEXT({collection}, "content", @query, @k)
|
|
165
|
+
RETURN {{
|
|
166
|
+
content: doc.content,
|
|
167
|
+
metadata: doc.metadata,
|
|
168
|
+
_key: doc._key
|
|
169
|
+
}}
|
|
170
|
+
"""
|
|
171
|
+
|
|
172
|
+
cursor = await db.aql.execute(
|
|
173
|
+
aql,
|
|
174
|
+
bind_vars={'query': query, 'k': k}
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
results = []
|
|
178
|
+
async for idx, doc in enumerate(cursor):
|
|
179
|
+
results.append(
|
|
180
|
+
SearchResult(
|
|
181
|
+
content=doc['content'],
|
|
182
|
+
metadata=doc.get('metadata', {}),
|
|
183
|
+
score=1.0 / (idx + 1), # Simple ranking score
|
|
184
|
+
source='arango',
|
|
185
|
+
original_rank=idx
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return results
|
|
190
|
+
|
|
191
|
+
except Exception as e:
|
|
192
|
+
print(f"ArangoDB search error: {e}")
|
|
193
|
+
return []
|
|
194
|
+
|
|
195
|
+
def _prepare_bm25_corpus(
|
|
196
|
+
self,
|
|
197
|
+
results: List[SearchResult]
|
|
198
|
+
) -> Tuple[List[List[str]], List[SearchResult]]:
|
|
199
|
+
"""Prepare corpus for BM25 tokenization"""
|
|
200
|
+
corpus = []
|
|
201
|
+
valid_results = []
|
|
202
|
+
|
|
203
|
+
for result in results:
|
|
204
|
+
# Simple tokenization - enhance with proper tokenizer if needed
|
|
205
|
+
if tokens := result.content.lower().split():
|
|
206
|
+
corpus.append(tokens)
|
|
207
|
+
valid_results.append(result)
|
|
208
|
+
|
|
209
|
+
return corpus, valid_results
|
|
210
|
+
|
|
211
|
+
def _rerank_with_bm25(
|
|
212
|
+
self,
|
|
213
|
+
query: str,
|
|
214
|
+
results: List[SearchResult]
|
|
215
|
+
) -> List[SearchResult]:
|
|
216
|
+
"""
|
|
217
|
+
Rerank results using BM25S algorithm
|
|
218
|
+
|
|
219
|
+
BM25S is an improved variant that considers document length
|
|
220
|
+
and applies saturation to term frequencies.
|
|
221
|
+
"""
|
|
222
|
+
if not results:
|
|
223
|
+
return []
|
|
224
|
+
|
|
225
|
+
try:
|
|
226
|
+
# Prepare corpus
|
|
227
|
+
corpus, valid_results = self._prepare_bm25_corpus(results)
|
|
228
|
+
|
|
229
|
+
if not corpus:
|
|
230
|
+
return results
|
|
231
|
+
|
|
232
|
+
# Create BM25 index
|
|
233
|
+
retriever = bm25s.BM25()
|
|
234
|
+
retriever.index(corpus)
|
|
235
|
+
|
|
236
|
+
# Tokenize query
|
|
237
|
+
query_tokens = query.lower().split()
|
|
238
|
+
|
|
239
|
+
# Get BM25 scores
|
|
240
|
+
bm25_scores, _ = retriever.retrieve(
|
|
241
|
+
bm25s.tokenize([query_tokens]),
|
|
242
|
+
k=len(corpus)
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Combine BM25 scores with original scores and source weights
|
|
246
|
+
for idx, result in enumerate(valid_results):
|
|
247
|
+
bm25_score = float(bm25_scores[0][idx])
|
|
248
|
+
source_weight = self.bm25_weights.get(result.source, 1.0)
|
|
249
|
+
|
|
250
|
+
# Hybrid scoring: BM25 + original score + source weight
|
|
251
|
+
result.score = (
|
|
252
|
+
0.6 * bm25_score +
|
|
253
|
+
0.3 * result.score +
|
|
254
|
+
0.1 * source_weight
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
# Sort by combined score
|
|
258
|
+
valid_results.sort(key=lambda x: x.score, reverse=True)
|
|
259
|
+
|
|
260
|
+
return valid_results
|
|
261
|
+
|
|
262
|
+
except ImportError:
|
|
263
|
+
# Fallback: use rank-bm25 if bm25s not available
|
|
264
|
+
from rank_bm25 import BM25Okapi
|
|
265
|
+
|
|
266
|
+
corpus, valid_results = self._prepare_bm25_corpus(results)
|
|
267
|
+
|
|
268
|
+
if not corpus:
|
|
269
|
+
return results
|
|
270
|
+
|
|
271
|
+
bm25 = BM25Okapi(corpus)
|
|
272
|
+
query_tokens = query.lower().split()
|
|
273
|
+
bm25_scores = bm25.get_scores(query_tokens)
|
|
274
|
+
|
|
275
|
+
for idx, result in enumerate(valid_results):
|
|
276
|
+
source_weight = self.bm25_weights.get(result.source, 1.0)
|
|
277
|
+
result.score = (
|
|
278
|
+
0.6 * bm25_scores[idx] +
|
|
279
|
+
0.3 * result.score +
|
|
280
|
+
0.1 * source_weight
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
valid_results.sort(key=lambda x: x.score, reverse=True)
|
|
284
|
+
return valid_results
|
|
285
|
+
|
|
286
|
+
async def execute(
|
|
287
|
+
self,
|
|
288
|
+
query: str,
|
|
289
|
+
k: Optional[int] = None,
|
|
290
|
+
**kwargs
|
|
291
|
+
) -> List[Dict[str, Any]]:
|
|
292
|
+
"""
|
|
293
|
+
Execute multi-store search with BM25 reranking
|
|
294
|
+
|
|
295
|
+
Args:
|
|
296
|
+
query: Search query
|
|
297
|
+
k: Number of results to return (overrides default)
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
List of top-k reranked results
|
|
301
|
+
"""
|
|
302
|
+
k = k or self.k
|
|
303
|
+
|
|
304
|
+
# Prepare search tasks
|
|
305
|
+
tasks = []
|
|
306
|
+
|
|
307
|
+
if StoreType.PGVECTOR in self.enabled_stores:
|
|
308
|
+
tasks.append(self._search_pgvector(query, self.k_per_store))
|
|
309
|
+
|
|
310
|
+
if StoreType.FAISS in self.enabled_stores:
|
|
311
|
+
tasks.append(self._search_faiss(query, self.k_per_store))
|
|
312
|
+
|
|
313
|
+
if StoreType.ARANGO in self.enabled_stores:
|
|
314
|
+
tasks.append(self._search_arango(query, self.k_per_store))
|
|
315
|
+
|
|
316
|
+
# Execute searches concurrently
|
|
317
|
+
search_results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
318
|
+
|
|
319
|
+
# Flatten and filter results
|
|
320
|
+
all_results = []
|
|
321
|
+
for result_set in search_results:
|
|
322
|
+
if isinstance(result_set, list):
|
|
323
|
+
all_results.extend(result_set)
|
|
324
|
+
|
|
325
|
+
# Remove duplicates based on content similarity
|
|
326
|
+
all_results = self._deduplicate_results(all_results)
|
|
327
|
+
|
|
328
|
+
# Apply BM25 reranking
|
|
329
|
+
reranked_results = self._rerank_with_bm25(query, all_results)
|
|
330
|
+
|
|
331
|
+
# Return top-k
|
|
332
|
+
top_k = reranked_results[:k]
|
|
333
|
+
|
|
334
|
+
return [
|
|
335
|
+
{
|
|
336
|
+
'content': r.content,
|
|
337
|
+
'metadata': r.metadata,
|
|
338
|
+
'score': r.score,
|
|
339
|
+
'source': r.source,
|
|
340
|
+
'rank': idx + 1
|
|
341
|
+
}
|
|
342
|
+
for idx, r in enumerate(top_k)
|
|
343
|
+
]
|
|
344
|
+
|
|
345
|
+
def _deduplicate_results(
|
|
346
|
+
self,
|
|
347
|
+
results: List[SearchResult],
|
|
348
|
+
similarity_threshold: float = 0.9
|
|
349
|
+
) -> List[SearchResult]:
|
|
350
|
+
"""Remove near-duplicate results using simple similarity"""
|
|
351
|
+
if not results:
|
|
352
|
+
return []
|
|
353
|
+
|
|
354
|
+
unique_results = []
|
|
355
|
+
seen_contents = set()
|
|
356
|
+
|
|
357
|
+
for result in results:
|
|
358
|
+
# Simple deduplication - enhance with embedding similarity if needed
|
|
359
|
+
content_hash = hash(result.content[:100]) # Use first 100 chars
|
|
360
|
+
|
|
361
|
+
if content_hash not in seen_contents:
|
|
362
|
+
seen_contents.add(content_hash)
|
|
363
|
+
unique_results.append(result)
|
|
364
|
+
|
|
365
|
+
return unique_results
|
|
366
|
+
|
|
367
|
+
async def __call__(self, query: str, **kwargs) -> List[Dict[str, Any]]:
|
|
368
|
+
"""Convenience method for direct calling"""
|
|
369
|
+
return await self.execute(query, **kwargs)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NetworkNinja API Tool - Real World Implementation
|
|
3
|
+
Complete implementation for NetworkNinja batch processing API
|
|
4
|
+
"""
|
|
5
|
+
import os
|
|
6
|
+
from typing import Optional
|
|
7
|
+
from navconfig import config
|
|
8
|
+
from pydantic import BaseModel, Field
|
|
9
|
+
from .resttool import RESTTool
|
|
10
|
+
from . import ToolResult
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# Configuration
|
|
15
|
+
# ============================================================================
|
|
16
|
+
|
|
17
|
+
# Environment from config or environment variable
|
|
18
|
+
NETWORKNINJA_ENV = config.get("NETWORKNINJA_ENV", "production") # dev, staging, prod
|
|
19
|
+
NETWORKNINJA_API_KEY = config.get("NETWORKNINJA_API_KEY")
|
|
20
|
+
NETWORKNINJA_BASE_URL = config.get(
|
|
21
|
+
"NETWORKNINJA_BASE_URL",
|
|
22
|
+
"https://api.networkninja.com"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class NetworkNinjaArgsSchema(BaseModel):
|
|
27
|
+
"""Schema for NetworkNinja API calls."""
|
|
28
|
+
action: str = Field(
|
|
29
|
+
description="Action to perform: get_batch, get_batches"
|
|
30
|
+
)
|
|
31
|
+
batch_id: Optional[str] = Field(
|
|
32
|
+
default=None,
|
|
33
|
+
description="Batch ID for get_batch operation"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class NetworkNinjaTool(RESTTool):
|
|
38
|
+
"""
|
|
39
|
+
NetworkNinja Batch Processing API Tool.
|
|
40
|
+
|
|
41
|
+
This tool provides access to NetworkNinja's batch processing capabilities.
|
|
42
|
+
It automatically handles environment-based URL routing and provides
|
|
43
|
+
convenient methods for batch operations.
|
|
44
|
+
|
|
45
|
+
Natural Language Examples:
|
|
46
|
+
- "please, run via GET get_batch for batch_id=xyz"
|
|
47
|
+
- "list all completed batches"
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
name = "networkninja_api"
|
|
51
|
+
description = """
|
|
52
|
+
NetworkNinja Batch Processing API provides access to:
|
|
53
|
+
- Batch status tracking
|
|
54
|
+
- Batch data retrieval
|
|
55
|
+
|
|
56
|
+
Use this tool when you need to:
|
|
57
|
+
- Get batch information by ID
|
|
58
|
+
- List batches
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
args_schema = NetworkNinjaArgsSchema
|
|
62
|
+
|
|
63
|
+
# Environment-specific configuration
|
|
64
|
+
ENV_PATHS = {
|
|
65
|
+
"dev": "dev",
|
|
66
|
+
"acceptance": "acceptance",
|
|
67
|
+
"prod": "production"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
def __init__(
|
|
71
|
+
self,
|
|
72
|
+
environment: str = NETWORKNINJA_ENV,
|
|
73
|
+
api_key: Optional[str] = None,
|
|
74
|
+
**kwargs
|
|
75
|
+
):
|
|
76
|
+
"""
|
|
77
|
+
Initialize NetworkNinja API tool.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
environment: Environment (dev, staging, prod)
|
|
81
|
+
api_key: API key for authentication
|
|
82
|
+
**kwargs: Additional arguments
|
|
83
|
+
"""
|
|
84
|
+
# Construct base URL with environment path
|
|
85
|
+
env_path = self.ENV_PATHS.get(environment, "production")
|
|
86
|
+
base_url = f"{NETWORKNINJA_BASE_URL}/{env_path}"
|
|
87
|
+
super().__init__(
|
|
88
|
+
base_url=base_url,
|
|
89
|
+
api_key=api_key,
|
|
90
|
+
use_http2=True, # Enable HTTP/2 for better performance
|
|
91
|
+
headers={
|
|
92
|
+
"Content-Type": "application/json",
|
|
93
|
+
"Accept": "application/json",
|
|
94
|
+
"X-Api-Key": NETWORKNINJA_API_KEY
|
|
95
|
+
},
|
|
96
|
+
**kwargs
|
|
97
|
+
)
|
|
98
|
+
self.environment = environment
|
|
99
|
+
|
|
100
|
+
async def _execute(
|
|
101
|
+
self,
|
|
102
|
+
action: str,
|
|
103
|
+
batch_id: Optional[str] = None,
|
|
104
|
+
**kwargs
|
|
105
|
+
) -> ToolResult:
|
|
106
|
+
"""
|
|
107
|
+
Execute NetworkNinja API action.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
action: Action to perform (get_batch, create_batch, etc.)
|
|
111
|
+
batch_id: Batch ID for specific operations
|
|
112
|
+
**kwargs: Additional arguments
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
ToolResult with API response
|
|
116
|
+
"""
|
|
117
|
+
# Route to appropriate method based on action
|
|
118
|
+
action_map = {
|
|
119
|
+
"get_batch": self._get_batch,
|
|
120
|
+
"list_batches": self._list_batches,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
handler = action_map.get(action)
|
|
124
|
+
|
|
125
|
+
if not handler:
|
|
126
|
+
return ToolResult(
|
|
127
|
+
status="error",
|
|
128
|
+
result=None,
|
|
129
|
+
error=f"Unknown action: {action}. Available: {list(action_map.keys())}",
|
|
130
|
+
metadata={"action": action}
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Call the appropriate handler
|
|
134
|
+
return await handler(
|
|
135
|
+
batch_id=batch_id,
|
|
136
|
+
**kwargs
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
async def _get_batch(
|
|
140
|
+
self,
|
|
141
|
+
batch_id: str,
|
|
142
|
+
**kwargs
|
|
143
|
+
) -> ToolResult:
|
|
144
|
+
"""Get batch by ID."""
|
|
145
|
+
if not batch_id:
|
|
146
|
+
return ToolResult(
|
|
147
|
+
status="error",
|
|
148
|
+
result=None,
|
|
149
|
+
error="batch_id is required for get_batch",
|
|
150
|
+
metadata={"action": "get_batch"}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
return await self._make_request(
|
|
154
|
+
endpoint="get_batch",
|
|
155
|
+
method="GET",
|
|
156
|
+
params={"batch_id": batch_id}
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
async def _list_batches(
|
|
160
|
+
self,
|
|
161
|
+
**kwargs
|
|
162
|
+
) -> ToolResult:
|
|
163
|
+
"""List batches with optional filters."""
|
|
164
|
+
return await self._make_request(
|
|
165
|
+
endpoint="get_batch",
|
|
166
|
+
method="GET"
|
|
167
|
+
)
|