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,434 @@
|
|
|
1
|
+
"""
|
|
2
|
+
HR-specific orchestrator and crew factories.
|
|
3
|
+
"""
|
|
4
|
+
from typing import List, Dict
|
|
5
|
+
from ..agent import BasicAgent
|
|
6
|
+
from .agent import OrchestratorAgent
|
|
7
|
+
from .crew import AgentCrew
|
|
8
|
+
from ...tools.abstract import AbstractTool
|
|
9
|
+
from ...tools.manager import ToolManager
|
|
10
|
+
from ...stores.abstract import AbstractStore
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class HRAgentFactory:
|
|
14
|
+
"""Factory for creating HR-specific agent orchestration systems."""
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def create_hr_orchestrator(
|
|
18
|
+
hr_agent: BasicAgent = None,
|
|
19
|
+
employee_data_agent: BasicAgent = None,
|
|
20
|
+
shared_tools: List[AbstractTool] = None
|
|
21
|
+
) -> OrchestratorAgent:
|
|
22
|
+
"""
|
|
23
|
+
Create an HR orchestrator with specialized agents.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
hr_agent: Agent for HR policies and procedures
|
|
27
|
+
employee_data_agent: Agent for employee data access
|
|
28
|
+
shared_tools: Tools to share between agents
|
|
29
|
+
"""
|
|
30
|
+
orchestrator = OrchestratorAgent(
|
|
31
|
+
name="HROrchestrator",
|
|
32
|
+
orchestration_prompt="""
|
|
33
|
+
You are an HR assistance orchestrator that helps employees with their questions
|
|
34
|
+
by consulting specialized agents for different types of information.
|
|
35
|
+
|
|
36
|
+
Your available agents:
|
|
37
|
+
- HR Policy Agent: Handles company policies, procedures, benefits, and general HR questions
|
|
38
|
+
- Employee Data Agent: Provides employee profile information, job details, salary, and organizational data
|
|
39
|
+
|
|
40
|
+
For employee questions:
|
|
41
|
+
- Use hr_policy_agent for policy, procedure, and general HR questions
|
|
42
|
+
- Use employee_data_agent for specific employee information (profile, salary, position)
|
|
43
|
+
- Combine responses when both perspectives are needed
|
|
44
|
+
- Always ensure data privacy and access controls are respected
|
|
45
|
+
- Provide a unified, comprehensive answer that addresses all aspects of the question
|
|
46
|
+
"""
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# Add shared tools if provided
|
|
50
|
+
if shared_tools:
|
|
51
|
+
for tool in shared_tools:
|
|
52
|
+
orchestrator.tool_manager.add_tool(tool)
|
|
53
|
+
|
|
54
|
+
# Add HR agent if provided
|
|
55
|
+
if hr_agent:
|
|
56
|
+
orchestrator.add_agent(
|
|
57
|
+
hr_agent,
|
|
58
|
+
tool_name="hr_policy_agent",
|
|
59
|
+
description="Handles HR policies, procedures, benefits, and general HR questions using company knowledge base"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Add employee data agent if provided
|
|
63
|
+
if employee_data_agent:
|
|
64
|
+
orchestrator.add_agent(
|
|
65
|
+
employee_data_agent,
|
|
66
|
+
tool_name="employee_data_agent",
|
|
67
|
+
description="Provides employee profile information, job details, salary, and organizational data"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
return orchestrator
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def create_hr_crew(
|
|
74
|
+
agents: List[BasicAgent],
|
|
75
|
+
shared_tools: List[AbstractTool] = None
|
|
76
|
+
) -> AgentCrew:
|
|
77
|
+
"""
|
|
78
|
+
Create an HR processing crew that processes requests in sequence.
|
|
79
|
+
|
|
80
|
+
Example sequence: Policy Check → Data Validation → Response Generation
|
|
81
|
+
"""
|
|
82
|
+
shared_tool_manager = ToolManager()
|
|
83
|
+
|
|
84
|
+
# Add shared tools
|
|
85
|
+
if shared_tools:
|
|
86
|
+
for tool in shared_tools:
|
|
87
|
+
shared_tool_manager.add_tool(tool)
|
|
88
|
+
|
|
89
|
+
crew = AgentCrew(
|
|
90
|
+
name="HRProcessingCrew",
|
|
91
|
+
agents=agents,
|
|
92
|
+
shared_tool_manager=shared_tool_manager
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return crew
|
|
96
|
+
|
|
97
|
+
class RAGHRAgent(BasicAgent):
|
|
98
|
+
"""
|
|
99
|
+
HR Agent with RAG capabilities using your existing vector store system.
|
|
100
|
+
|
|
101
|
+
This agent specializes in company policies, procedures, and HR documentation.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
def __init__(
|
|
105
|
+
self,
|
|
106
|
+
vector_store: AbstractStore = None,
|
|
107
|
+
knowledge_threshold: float = 0.7,
|
|
108
|
+
max_context_docs: int = 5,
|
|
109
|
+
**kwargs
|
|
110
|
+
):
|
|
111
|
+
# Set HR-specific system prompt
|
|
112
|
+
hr_system_prompt = kwargs.pop('system_prompt', None) or """
|
|
113
|
+
You are an HR Policy Specialist with comprehensive knowledge of company policies, procedures, and HR documentation.
|
|
114
|
+
|
|
115
|
+
Your expertise covers:
|
|
116
|
+
- Employee benefits and compensation policies
|
|
117
|
+
- Leave policies (vacation, sick, personal, parental)
|
|
118
|
+
- Performance review processes and procedures
|
|
119
|
+
- Company policies and employee handbook
|
|
120
|
+
- Compliance requirements and regulations
|
|
121
|
+
- Employee development and training programs
|
|
122
|
+
- Workplace policies and guidelines
|
|
123
|
+
|
|
124
|
+
When answering questions:
|
|
125
|
+
1. Always search the knowledge base first for accurate, current information
|
|
126
|
+
2. Provide specific policy references when available
|
|
127
|
+
3. Explain both the policy and its practical implications
|
|
128
|
+
4. If information isn't in the knowledge base, clearly state this limitation
|
|
129
|
+
5. Maintain confidentiality and follow data privacy guidelines
|
|
130
|
+
6. Provide actionable guidance when possible
|
|
131
|
+
|
|
132
|
+
Always base your responses on official company documentation.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
super().__init__(
|
|
136
|
+
name="HRPolicyAgent",
|
|
137
|
+
system_prompt=hr_system_prompt,
|
|
138
|
+
**kwargs
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
self.vector_store = vector_store
|
|
142
|
+
self.knowledge_threshold = knowledge_threshold
|
|
143
|
+
self.max_context_docs = max_context_docs
|
|
144
|
+
|
|
145
|
+
# Add RAG capabilities if vector store is provided
|
|
146
|
+
if self.vector_store:
|
|
147
|
+
self._setup_rag_tools()
|
|
148
|
+
|
|
149
|
+
def _setup_rag_tools(self):
|
|
150
|
+
"""Setup RAG tools for HR knowledge base search."""
|
|
151
|
+
|
|
152
|
+
class HRKnowledgeSearchTool(AbstractTool):
|
|
153
|
+
"""Tool for searching HR knowledge base."""
|
|
154
|
+
|
|
155
|
+
def __init__(self, vector_store, threshold, max_docs):
|
|
156
|
+
super().__init__()
|
|
157
|
+
self.vector_store = vector_store
|
|
158
|
+
self.threshold = threshold
|
|
159
|
+
self.max_docs = max_docs
|
|
160
|
+
self.name = "search_hr_policies"
|
|
161
|
+
self.description = "Search the HR knowledge base for company policies, procedures, and documentation"
|
|
162
|
+
|
|
163
|
+
self.input_schema = {
|
|
164
|
+
"type": "object",
|
|
165
|
+
"properties": {
|
|
166
|
+
"query": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"description": "Search query for HR policies and procedures"
|
|
169
|
+
},
|
|
170
|
+
"search_type": {
|
|
171
|
+
"type": "string",
|
|
172
|
+
"enum": ["similarity", "mmr", "ensemble"],
|
|
173
|
+
"description": "Type of search to perform",
|
|
174
|
+
"default": "similarity"
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"required": ["query"],
|
|
178
|
+
"additionalProperties": False
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async def _execute(self, query: str, search_type: str = "similarity", **kwargs) -> str:
|
|
182
|
+
"""Execute knowledge base search."""
|
|
183
|
+
try:
|
|
184
|
+
# Use your existing vector store search
|
|
185
|
+
results = await self.vector_store.asearch(
|
|
186
|
+
query=query,
|
|
187
|
+
search_type=search_type,
|
|
188
|
+
limit=self.max_docs,
|
|
189
|
+
score_threshold=self.threshold
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
if not results:
|
|
193
|
+
return "No relevant policy information found in the knowledge base."
|
|
194
|
+
|
|
195
|
+
# Format results for context
|
|
196
|
+
context_parts = []
|
|
197
|
+
for i, result in enumerate(results, 1):
|
|
198
|
+
# Assuming your vector store returns documents with content and metadata
|
|
199
|
+
title = getattr(result, 'title', f'Document {i}')
|
|
200
|
+
content = getattr(result, 'content', str(result))
|
|
201
|
+
source = getattr(result, 'source', 'Unknown')
|
|
202
|
+
|
|
203
|
+
context_parts.append(f"**Policy Document {i}: {title}**")
|
|
204
|
+
context_parts.append(f"Source: {source}")
|
|
205
|
+
context_parts.append(f"Content: {content}")
|
|
206
|
+
context_parts.append("---")
|
|
207
|
+
|
|
208
|
+
return "\n".join(context_parts)
|
|
209
|
+
|
|
210
|
+
except Exception as e:
|
|
211
|
+
return f"Error searching HR knowledge base: {str(e)}"
|
|
212
|
+
|
|
213
|
+
# Add the HR knowledge search tool
|
|
214
|
+
hr_search_tool = HRKnowledgeSearchTool(
|
|
215
|
+
self.vector_store,
|
|
216
|
+
self.knowledge_threshold,
|
|
217
|
+
self.max_context_docs
|
|
218
|
+
)
|
|
219
|
+
self.tool_manager.add_tool(hr_search_tool)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class EmployeeDataAgent(BasicAgent):
|
|
223
|
+
"""
|
|
224
|
+
Agent specialized in employee profile and organizational data.
|
|
225
|
+
|
|
226
|
+
This agent handles employee-specific information like profiles, positions, salary data.
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
def __init__(
|
|
230
|
+
self,
|
|
231
|
+
employee_database=None,
|
|
232
|
+
access_control_rules: Dict[str, List[str]] = None,
|
|
233
|
+
**kwargs
|
|
234
|
+
):
|
|
235
|
+
employee_system_prompt = kwargs.pop('system_prompt', None) or """
|
|
236
|
+
You are an Employee Data Specialist with secure access to employee information and organizational data.
|
|
237
|
+
|
|
238
|
+
Your capabilities include:
|
|
239
|
+
- Employee profiles and contact information
|
|
240
|
+
- Current job positions and organizational hierarchy
|
|
241
|
+
- Salary and compensation data (when authorized)
|
|
242
|
+
- Performance records (when authorized)
|
|
243
|
+
- Team and department assignments
|
|
244
|
+
- Employment history and tenure information
|
|
245
|
+
|
|
246
|
+
Security and Privacy Guidelines:
|
|
247
|
+
- Always verify user authorization before accessing sensitive data
|
|
248
|
+
- Only provide information the requesting user is authorized to see
|
|
249
|
+
- Log all data access requests for audit purposes
|
|
250
|
+
- Never expose raw database queries or technical implementation details
|
|
251
|
+
- Respect confidentiality levels and data classification
|
|
252
|
+
- Follow GDPR and other applicable privacy regulations
|
|
253
|
+
|
|
254
|
+
When handling requests:
|
|
255
|
+
1. Check user authorization for the requested data type
|
|
256
|
+
2. Query only the specific information needed
|
|
257
|
+
3. Format responses in a clear, professional manner
|
|
258
|
+
4. Include appropriate disclaimers for sensitive information
|
|
259
|
+
5. Suggest alternative approaches if access is restricted
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
super().__init__(
|
|
263
|
+
name="EmployeeDataAgent",
|
|
264
|
+
system_prompt=employee_system_prompt,
|
|
265
|
+
**kwargs
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
self.employee_database = employee_database
|
|
269
|
+
self.access_rules = access_control_rules or {
|
|
270
|
+
'salary_data': ['self', 'manager', 'hr'],
|
|
271
|
+
'personal_info': ['self', 'hr'],
|
|
272
|
+
'performance_data': ['self', 'manager', 'hr'],
|
|
273
|
+
'contact_info': ['all'],
|
|
274
|
+
'organizational_data': ['all']
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
# Add employee data tools if database is provided
|
|
278
|
+
if self.employee_database:
|
|
279
|
+
self._setup_employee_data_tools()
|
|
280
|
+
|
|
281
|
+
def _setup_employee_data_tools(self):
|
|
282
|
+
"""Setup employee data access tools with security controls."""
|
|
283
|
+
|
|
284
|
+
class EmployeeProfileTool(AbstractTool):
|
|
285
|
+
"""Tool for accessing employee profile information."""
|
|
286
|
+
|
|
287
|
+
def __init__(self, database, access_rules):
|
|
288
|
+
super().__init__()
|
|
289
|
+
self.database = database
|
|
290
|
+
self.access_rules = access_rules
|
|
291
|
+
self.name = "get_employee_profile"
|
|
292
|
+
self.description = "Get employee profile information including position, department, and contact details"
|
|
293
|
+
|
|
294
|
+
self.input_schema = {
|
|
295
|
+
"type": "object",
|
|
296
|
+
"properties": {
|
|
297
|
+
"employee_id": {
|
|
298
|
+
"type": "string",
|
|
299
|
+
"description": "Employee ID to lookup"
|
|
300
|
+
},
|
|
301
|
+
"requesting_user_id": {
|
|
302
|
+
"type": "string",
|
|
303
|
+
"description": "ID of user making the request"
|
|
304
|
+
},
|
|
305
|
+
"data_types": {
|
|
306
|
+
"type": "array",
|
|
307
|
+
"items": {
|
|
308
|
+
"type": "string",
|
|
309
|
+
"enum": ["profile", "position", "contact", "salary", "performance"]
|
|
310
|
+
},
|
|
311
|
+
"description": "Types of data to retrieve"
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
"required": ["employee_id", "requesting_user_id"],
|
|
315
|
+
"additionalProperties": False
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async def _execute(
|
|
319
|
+
self,
|
|
320
|
+
employee_id: str,
|
|
321
|
+
requesting_user_id: str,
|
|
322
|
+
data_types: List[str] = None,
|
|
323
|
+
**kwargs
|
|
324
|
+
) -> str:
|
|
325
|
+
"""Execute employee data query with access controls."""
|
|
326
|
+
try:
|
|
327
|
+
# Check authorization for each data type
|
|
328
|
+
authorized_data = []
|
|
329
|
+
denied_data = []
|
|
330
|
+
|
|
331
|
+
data_types = data_types or ['profile', 'position', 'contact']
|
|
332
|
+
|
|
333
|
+
for data_type in data_types:
|
|
334
|
+
if self._check_access(requesting_user_id, employee_id, data_type):
|
|
335
|
+
authorized_data.append(data_type)
|
|
336
|
+
else:
|
|
337
|
+
denied_data.append(data_type)
|
|
338
|
+
|
|
339
|
+
if not authorized_data:
|
|
340
|
+
return f"Access denied: No authorization for requested data types: {', '.join(data_types)}"
|
|
341
|
+
|
|
342
|
+
# Query database for authorized data
|
|
343
|
+
# This is where you'd integrate with your actual employee database
|
|
344
|
+
result_parts = []
|
|
345
|
+
|
|
346
|
+
if 'profile' in authorized_data:
|
|
347
|
+
# Mock data - replace with actual database query
|
|
348
|
+
result_parts.append(f"Employee Profile for {employee_id}:")
|
|
349
|
+
result_parts.append(f"- Name: [Retrieved from database]")
|
|
350
|
+
result_parts.append(f"- Employee ID: {employee_id}")
|
|
351
|
+
result_parts.append(f"- Start Date: [Retrieved from database]")
|
|
352
|
+
|
|
353
|
+
if 'position' in authorized_data:
|
|
354
|
+
result_parts.append(f"Position Information:")
|
|
355
|
+
result_parts.append(f"- Title: [Retrieved from database]")
|
|
356
|
+
result_parts.append(f"- Department: [Retrieved from database]")
|
|
357
|
+
result_parts.append(f"- Manager: [Retrieved from database]")
|
|
358
|
+
|
|
359
|
+
if 'salary' in authorized_data:
|
|
360
|
+
result_parts.append(f"Compensation Information:")
|
|
361
|
+
result_parts.append(f"- Salary: [Retrieved from database]")
|
|
362
|
+
result_parts.append(f"- Last Review: [Retrieved from database]")
|
|
363
|
+
|
|
364
|
+
result = "\n".join(result_parts)
|
|
365
|
+
|
|
366
|
+
if denied_data:
|
|
367
|
+
result += f"\n\nNote: Access denied for: {', '.join(denied_data)}"
|
|
368
|
+
|
|
369
|
+
return result
|
|
370
|
+
|
|
371
|
+
except Exception as e:
|
|
372
|
+
return f"Error retrieving employee data: {str(e)}"
|
|
373
|
+
|
|
374
|
+
def _check_access(self, requesting_user: str, target_employee: str, data_type: str) -> bool:
|
|
375
|
+
"""Check if user has access to specific data type."""
|
|
376
|
+
# Simplified access control - replace with your actual logic
|
|
377
|
+
|
|
378
|
+
# Users can always access their own basic info
|
|
379
|
+
if requesting_user == target_employee and data_type in ['profile', 'position', 'contact']:
|
|
380
|
+
return True
|
|
381
|
+
|
|
382
|
+
# Check access rules
|
|
383
|
+
allowed_roles = self.access_rules.get(data_type, [])
|
|
384
|
+
|
|
385
|
+
# This is where you'd check the user's actual role
|
|
386
|
+
# For demo purposes, we'll assume some basic logic
|
|
387
|
+
if 'all' in allowed_roles:
|
|
388
|
+
return True
|
|
389
|
+
|
|
390
|
+
# Add your actual role checking logic here
|
|
391
|
+
return False
|
|
392
|
+
|
|
393
|
+
class VacationBalanceTool(AbstractTool):
|
|
394
|
+
"""Tool for checking vacation day balances."""
|
|
395
|
+
|
|
396
|
+
def __init__(self, database):
|
|
397
|
+
super().__init__()
|
|
398
|
+
self.database = database
|
|
399
|
+
self.name = "get_vacation_balance"
|
|
400
|
+
self.description = "Get current vacation day balance and accrual information"
|
|
401
|
+
|
|
402
|
+
self.input_schema = {
|
|
403
|
+
"type": "object",
|
|
404
|
+
"properties": {
|
|
405
|
+
"employee_id": {
|
|
406
|
+
"type": "string",
|
|
407
|
+
"description": "Employee ID to check balance for"
|
|
408
|
+
}
|
|
409
|
+
},
|
|
410
|
+
"required": ["employee_id"],
|
|
411
|
+
"additionalProperties": False
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
async def _execute(self, employee_id: str, **kwargs) -> str:
|
|
415
|
+
"""Get vacation balance information."""
|
|
416
|
+
try:
|
|
417
|
+
# Mock vacation data - replace with actual database query
|
|
418
|
+
return f"""Vacation Balance for Employee {employee_id}:
|
|
419
|
+
- Current Available Days: 15.5 days
|
|
420
|
+
- Used This Year: 4.5 days
|
|
421
|
+
- Total Annual Allocation: 20 days
|
|
422
|
+
- Accrual Rate: 1.67 days per month
|
|
423
|
+
- Next Accrual Date: End of current month
|
|
424
|
+
- Rollover Limit: 5 days maximum"""
|
|
425
|
+
|
|
426
|
+
except Exception as e:
|
|
427
|
+
return f"Error retrieving vacation balance: {str(e)}"
|
|
428
|
+
|
|
429
|
+
# Add employee data tools
|
|
430
|
+
profile_tool = EmployeeProfileTool(self.employee_database, self.access_rules)
|
|
431
|
+
vacation_tool = VacationBalanceTool(self.employee_database)
|
|
432
|
+
|
|
433
|
+
self.tool_manager.add_tool(profile_tool)
|
|
434
|
+
self.tool_manager.add_tool(vacation_tool)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from typing import Dict, List, Optional, Any
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
import asyncio
|
|
4
|
+
from ....models.crew import AgentResult
|
|
5
|
+
from .mixin import VectorStoreMixin
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class ExecutionMemory(VectorStoreMixin):
|
|
9
|
+
"""In-memory storage for execution history"""
|
|
10
|
+
original_query: Optional[str] = None
|
|
11
|
+
results: Dict[str, AgentResult] = field(default_factory=dict)
|
|
12
|
+
execution_graph: Dict[str, List[str]] = field(default_factory=dict)
|
|
13
|
+
execution_order: List[str] = field(default_factory=list)
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self, original_query: str = "",
|
|
17
|
+
embedding_model=None,
|
|
18
|
+
dimension: int = 384,
|
|
19
|
+
index_type: str = "Flat" # "Flat", "FlatIP", o "HNSW"
|
|
20
|
+
):
|
|
21
|
+
self.original_query = original_query
|
|
22
|
+
self.results = {}
|
|
23
|
+
self.execution_graph = {}
|
|
24
|
+
self.execution_order = []
|
|
25
|
+
# Initialize mixin
|
|
26
|
+
VectorStoreMixin.__init__(
|
|
27
|
+
self,
|
|
28
|
+
embedding_model=embedding_model,
|
|
29
|
+
dimension=dimension,
|
|
30
|
+
index_type=index_type
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def add_result(self, result: AgentResult, vectorize: bool = True):
|
|
34
|
+
"""Add a result and update execution graph"""
|
|
35
|
+
self.results[result.agent_id] = result
|
|
36
|
+
if result.parent_execution_id:
|
|
37
|
+
if result.parent_execution_id not in self.execution_graph:
|
|
38
|
+
self.execution_graph[result.parent_execution_id] = []
|
|
39
|
+
self.execution_graph[result.parent_execution_id].append(result.execution_id)
|
|
40
|
+
|
|
41
|
+
# Async vectorization if enabled
|
|
42
|
+
if vectorize and self.embedding_model:
|
|
43
|
+
asyncio.create_task(
|
|
44
|
+
self._vectorize_result_async(result)
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
def get_results_by_agent(self, agent_id: str) -> AgentResult:
|
|
48
|
+
"""Retrieve result from a specific agent"""
|
|
49
|
+
return self.results.get(agent_id)
|
|
50
|
+
|
|
51
|
+
def get_reexecuted_results(self) -> List[AgentResult]:
|
|
52
|
+
"""Get only results from re-executions triggered by ask()"""
|
|
53
|
+
return [r for r in self.results.values() if r.parent_execution_id is not None]
|
|
54
|
+
|
|
55
|
+
def get_context_for_agent(self, agent_id: str) -> Any:
|
|
56
|
+
idx = self.execution_order.index(agent_id)
|
|
57
|
+
if idx == 0:
|
|
58
|
+
return self.original_query
|
|
59
|
+
prev_agent_id = self.execution_order[idx - 1]
|
|
60
|
+
return self.results[prev_agent_id].result
|
|
61
|
+
|
|
62
|
+
def clear(self, keep_query: bool = False):
|
|
63
|
+
"""
|
|
64
|
+
Clear execution memory.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
keep_query: If True, preserves the original_query. Useful for re-running
|
|
68
|
+
the same query with fresh execution.
|
|
69
|
+
"""
|
|
70
|
+
self.results.clear()
|
|
71
|
+
self.execution_graph.clear()
|
|
72
|
+
self.execution_order.clear()
|
|
73
|
+
self._clear_vectors()
|
|
74
|
+
|
|
75
|
+
if not keep_query:
|
|
76
|
+
self.original_query = ""
|
|
77
|
+
|
|
78
|
+
def get_snapshot(self) -> Dict[str, Any]:
|
|
79
|
+
"""
|
|
80
|
+
Get a snapshot of current memory state for inspection.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Dictionary with all memory state information
|
|
84
|
+
"""
|
|
85
|
+
return {
|
|
86
|
+
"original_query": self.original_query,
|
|
87
|
+
"results": {
|
|
88
|
+
agent_id: {
|
|
89
|
+
"content": result.content,
|
|
90
|
+
"metadata": result.metadata,
|
|
91
|
+
"timestamp": result.timestamp.isoformat(),
|
|
92
|
+
"parent_execution_id": result.parent_execution_id
|
|
93
|
+
}
|
|
94
|
+
for agent_id, result in self.results.items()
|
|
95
|
+
},
|
|
96
|
+
"execution_order": self.execution_order.copy(),
|
|
97
|
+
"execution_graph": {k: v.copy() for k, v in self.execution_graph.items()},
|
|
98
|
+
"total_executions": len(self.results),
|
|
99
|
+
"reexecutions": len(self.get_reexecuted_results())
|
|
100
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
from typing import List, Tuple, Optional, Any
|
|
2
|
+
from ....models.crew import AgentResult, VectorStoreProtocol
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class VectorStoreMixin:
|
|
6
|
+
"""Mixin to add FAISS vector store capabilities to ExecutionMemory"""
|
|
7
|
+
|
|
8
|
+
def __init__(
|
|
9
|
+
self,
|
|
10
|
+
*args,
|
|
11
|
+
embedding_model: Optional[VectorStoreProtocol] = None,
|
|
12
|
+
dimension: int = 384,
|
|
13
|
+
index_type: str = "Flat",
|
|
14
|
+
**kwargs
|
|
15
|
+
):
|
|
16
|
+
super().__init__(*args, **kwargs)
|
|
17
|
+
import faiss # Ensure faiss is available
|
|
18
|
+
self.embedding_model = embedding_model
|
|
19
|
+
self.dimension = dimension
|
|
20
|
+
self._faiss_index: Optional[Any] = None
|
|
21
|
+
self._vector_chunks: List[Tuple[str, str]] = [] # (chunk_text, agent_id)
|
|
22
|
+
|
|
23
|
+
if embedding_model:
|
|
24
|
+
from sentence_transformers import SentenceTransformer
|
|
25
|
+
if isinstance(embedding_model, str):
|
|
26
|
+
self.embedding_model = SentenceTransformer(embedding_model)
|
|
27
|
+
try:
|
|
28
|
+
# Initialize FAISS index based on type
|
|
29
|
+
if index_type == "FlatIP":
|
|
30
|
+
self._faiss_index = faiss.IndexFlatIP(dimension)
|
|
31
|
+
elif index_type == "HNSW":
|
|
32
|
+
self._faiss_index = faiss.IndexHNSWFlat(dimension, 32, faiss.METRIC_INNER_PRODUCT)
|
|
33
|
+
else: # Default to FlatL2
|
|
34
|
+
self._faiss_index = faiss.IndexFlatL2(dimension)
|
|
35
|
+
|
|
36
|
+
except ImportError:
|
|
37
|
+
self._faiss_index = None
|
|
38
|
+
|
|
39
|
+
def _chunk_result(self, result: AgentResult) -> List[str]:
|
|
40
|
+
"""Break down result into semantically meaningful chunks"""
|
|
41
|
+
text = result.to_text()
|
|
42
|
+
|
|
43
|
+
# Simple chunking - can be enhanced
|
|
44
|
+
if len(text) < 500:
|
|
45
|
+
return [text]
|
|
46
|
+
|
|
47
|
+
chunks = []
|
|
48
|
+
sections = text.split('\n\n')
|
|
49
|
+
current_chunk = []
|
|
50
|
+
current_length = 0
|
|
51
|
+
|
|
52
|
+
for section in sections:
|
|
53
|
+
if current_length + len(section) > 500 and current_chunk:
|
|
54
|
+
chunks.append('\n'.join(current_chunk))
|
|
55
|
+
current_chunk = [section]
|
|
56
|
+
current_length = len(section)
|
|
57
|
+
else:
|
|
58
|
+
current_chunk.append(section)
|
|
59
|
+
current_length += len(section)
|
|
60
|
+
|
|
61
|
+
if current_chunk:
|
|
62
|
+
chunks.append('\n'.join(current_chunk))
|
|
63
|
+
|
|
64
|
+
return chunks
|
|
65
|
+
|
|
66
|
+
async def _vectorize_result_async(self, result: AgentResult):
|
|
67
|
+
"""Async task to vectorize and index a result"""
|
|
68
|
+
if not self._faiss_available or not self.embedding_model or self._faiss_index is None:
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
# Chunk the result
|
|
72
|
+
chunks = self._chunk_result(result)
|
|
73
|
+
|
|
74
|
+
# Store chunks with agent reference
|
|
75
|
+
for chunk in chunks:
|
|
76
|
+
self._vector_chunks.append((chunk, result.agent_id))
|
|
77
|
+
|
|
78
|
+
# Generate embeddings for all chunks
|
|
79
|
+
all_texts = [chunk for chunk, _ in self._vector_chunks]
|
|
80
|
+
embeddings = self.embedding_model.encode(all_texts, convert_to_numpy=True)
|
|
81
|
+
|
|
82
|
+
# Ensure correct dtype and shape
|
|
83
|
+
embeddings = embeddings.astype('float32')
|
|
84
|
+
|
|
85
|
+
# Rebuild index with all embeddings
|
|
86
|
+
self._faiss_index.reset()
|
|
87
|
+
self._faiss_index.add(embeddings)
|
|
88
|
+
|
|
89
|
+
def search_similar(self, query: str, top_k: int = 5) -> List[Tuple[str, AgentResult, float]]:
|
|
90
|
+
"""Search for semantically similar result chunks"""
|
|
91
|
+
if not self._faiss_available or self._faiss_index is None or self._faiss_index.ntotal == 0:
|
|
92
|
+
return []
|
|
93
|
+
|
|
94
|
+
# Generate query embedding
|
|
95
|
+
query_embedding = self.embedding_model.encode([query], convert_to_numpy=True)
|
|
96
|
+
query_embedding = query_embedding.astype('float32')
|
|
97
|
+
|
|
98
|
+
# Ensure correct shape (1, dimension)
|
|
99
|
+
if len(query_embedding.shape) == 1:
|
|
100
|
+
query_embedding = query_embedding.reshape(1, -1)
|
|
101
|
+
|
|
102
|
+
# Search FAISS - API correcta
|
|
103
|
+
k = min(top_k, self._faiss_index.ntotal)
|
|
104
|
+
D, I = self._faiss_index.search(query_embedding, k)
|
|
105
|
+
|
|
106
|
+
results = []
|
|
107
|
+
for idx, distance in zip(I[0], D[0]):
|
|
108
|
+
if idx < len(self._vector_chunks) and idx >= 0: # idx puede ser -1 si no hay suficientes resultados
|
|
109
|
+
chunk_text, agent_id = self._vector_chunks[idx]
|
|
110
|
+
if (agent_result := self.results.get(agent_id)):
|
|
111
|
+
results.append((chunk_text, agent_result, float(distance)))
|
|
112
|
+
|
|
113
|
+
return results
|
|
114
|
+
|
|
115
|
+
def _clear_vectors(self):
|
|
116
|
+
"""Clear vector store data"""
|
|
117
|
+
self._vector_chunks.clear()
|
|
118
|
+
if self._faiss_index:
|
|
119
|
+
self._faiss_index.reset()
|