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,473 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Internal tools for the CodeInterpreterTool agent.
|
|
3
|
+
These tools provide the agent with capabilities for static analysis,
|
|
4
|
+
code execution, and file operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import ast
|
|
8
|
+
import hashlib
|
|
9
|
+
from typing import Dict, List, Any, Optional
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from dataclasses import dataclass, asdict
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class FunctionInfo:
|
|
16
|
+
"""Information about a function"""
|
|
17
|
+
name: str
|
|
18
|
+
lineno: int
|
|
19
|
+
args: List[str]
|
|
20
|
+
returns: Optional[str]
|
|
21
|
+
docstring: Optional[str]
|
|
22
|
+
decorators: List[str]
|
|
23
|
+
is_async: bool
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class ClassInfo:
|
|
28
|
+
"""Information about a class"""
|
|
29
|
+
name: str
|
|
30
|
+
lineno: int
|
|
31
|
+
bases: List[str]
|
|
32
|
+
methods: List[str]
|
|
33
|
+
docstring: Optional[str]
|
|
34
|
+
decorators: List[str]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class ImportInfo:
|
|
39
|
+
"""Information about an import"""
|
|
40
|
+
module: str
|
|
41
|
+
names: List[str]
|
|
42
|
+
is_from_import: bool
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class StaticAnalysisTool:
|
|
46
|
+
"""
|
|
47
|
+
Tool for performing static analysis on Python code.
|
|
48
|
+
Uses AST parsing and radon for complexity metrics.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def analyze_code_structure(self, code: str) -> Dict[str, Any]:
|
|
52
|
+
"""
|
|
53
|
+
Analyze code structure using AST.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
code: Python source code
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Dictionary with functions, classes, imports, and basic metrics
|
|
60
|
+
"""
|
|
61
|
+
try:
|
|
62
|
+
tree = ast.parse(code)
|
|
63
|
+
except SyntaxError as e:
|
|
64
|
+
return {
|
|
65
|
+
"error": f"Syntax error at line {e.lineno}: {e.msg}",
|
|
66
|
+
"success": False
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
functions = []
|
|
70
|
+
classes = []
|
|
71
|
+
imports = []
|
|
72
|
+
|
|
73
|
+
for node in ast.walk(tree):
|
|
74
|
+
if isinstance(node, ast.FunctionDef) or isinstance(node, ast.AsyncFunctionDef):
|
|
75
|
+
func_info = self._extract_function_info(node)
|
|
76
|
+
functions.append(asdict(func_info))
|
|
77
|
+
|
|
78
|
+
elif isinstance(node, ast.ClassDef):
|
|
79
|
+
class_info = self._extract_class_info(node)
|
|
80
|
+
classes.append(asdict(class_info))
|
|
81
|
+
|
|
82
|
+
elif isinstance(node, (ast.Import, ast.ImportFrom)):
|
|
83
|
+
import_info = self._extract_import_info(node)
|
|
84
|
+
imports.append(asdict(import_info))
|
|
85
|
+
|
|
86
|
+
# Calculate basic metrics
|
|
87
|
+
lines = code.split('\n')
|
|
88
|
+
total_lines = len(lines)
|
|
89
|
+
code_lines = len([l for l in lines if l.strip() and not l.strip().startswith('#')])
|
|
90
|
+
comment_lines = len([l for l in lines if l.strip().startswith('#')])
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
"success": True,
|
|
94
|
+
"functions": functions,
|
|
95
|
+
"classes": classes,
|
|
96
|
+
"imports": imports,
|
|
97
|
+
"metrics": {
|
|
98
|
+
"total_lines": total_lines,
|
|
99
|
+
"code_lines": code_lines,
|
|
100
|
+
"comment_lines": comment_lines,
|
|
101
|
+
"blank_lines": total_lines - code_lines - comment_lines
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
def _extract_function_info(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> FunctionInfo:
|
|
106
|
+
"""Extract information from a function node"""
|
|
107
|
+
args = [arg.arg for arg in node.args.args]
|
|
108
|
+
|
|
109
|
+
returns = None
|
|
110
|
+
if node.returns:
|
|
111
|
+
returns = ast.unparse(node.returns)
|
|
112
|
+
|
|
113
|
+
docstring = ast.get_docstring(node)
|
|
114
|
+
|
|
115
|
+
decorators = [ast.unparse(dec) for dec in node.decorator_list]
|
|
116
|
+
|
|
117
|
+
return FunctionInfo(
|
|
118
|
+
name=node.name,
|
|
119
|
+
lineno=node.lineno,
|
|
120
|
+
args=args,
|
|
121
|
+
returns=returns,
|
|
122
|
+
docstring=docstring,
|
|
123
|
+
decorators=decorators,
|
|
124
|
+
is_async=isinstance(node, ast.AsyncFunctionDef)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
def _extract_class_info(self, node: ast.ClassDef) -> ClassInfo:
|
|
128
|
+
"""Extract information from a class node"""
|
|
129
|
+
bases = [ast.unparse(base) for base in node.bases]
|
|
130
|
+
|
|
131
|
+
methods = []
|
|
132
|
+
for item in node.body:
|
|
133
|
+
if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
134
|
+
methods.append(item.name)
|
|
135
|
+
|
|
136
|
+
docstring = ast.get_docstring(node)
|
|
137
|
+
decorators = [ast.unparse(dec) for dec in node.decorator_list]
|
|
138
|
+
|
|
139
|
+
return ClassInfo(
|
|
140
|
+
name=node.name,
|
|
141
|
+
lineno=node.lineno,
|
|
142
|
+
bases=bases,
|
|
143
|
+
methods=methods,
|
|
144
|
+
docstring=docstring,
|
|
145
|
+
decorators=decorators
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
def _extract_import_info(self, node: ast.Import | ast.ImportFrom) -> ImportInfo:
|
|
149
|
+
"""Extract information from an import node"""
|
|
150
|
+
if isinstance(node, ast.Import):
|
|
151
|
+
return ImportInfo(
|
|
152
|
+
module=node.names[0].name if node.names else "",
|
|
153
|
+
names=[alias.name for alias in node.names],
|
|
154
|
+
is_from_import=False
|
|
155
|
+
)
|
|
156
|
+
else: # ImportFrom
|
|
157
|
+
return ImportInfo(
|
|
158
|
+
module=node.module or "",
|
|
159
|
+
names=[alias.name for alias in node.names],
|
|
160
|
+
is_from_import=True
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
def calculate_complexity(self, code: str) -> Dict[str, Any]:
|
|
164
|
+
"""
|
|
165
|
+
Calculate code complexity metrics using radon.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
code: Python source code
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Dictionary with complexity metrics
|
|
172
|
+
"""
|
|
173
|
+
try:
|
|
174
|
+
# Try to import radon
|
|
175
|
+
from radon.complexity import cc_visit
|
|
176
|
+
from radon.metrics import mi_visit, h_visit
|
|
177
|
+
|
|
178
|
+
# Cyclomatic Complexity
|
|
179
|
+
cc_results = cc_visit(code)
|
|
180
|
+
complexity_data = []
|
|
181
|
+
|
|
182
|
+
for item in cc_results:
|
|
183
|
+
complexity_data.append({
|
|
184
|
+
"name": item.name,
|
|
185
|
+
"complexity": item.complexity,
|
|
186
|
+
"lineno": item.lineno,
|
|
187
|
+
"type": item.classname or "function"
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
# Calculate average complexity
|
|
191
|
+
avg_complexity = sum(item.complexity for item in cc_results) / len(cc_results) if cc_results else 0
|
|
192
|
+
|
|
193
|
+
# Maintainability Index
|
|
194
|
+
mi_score = mi_visit(code, multi=True)
|
|
195
|
+
|
|
196
|
+
# Halstead metrics
|
|
197
|
+
h_metrics = h_visit(code)
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
"success": True,
|
|
201
|
+
"cyclomatic_complexity": {
|
|
202
|
+
"average": round(avg_complexity, 2),
|
|
203
|
+
"total": sum(item.complexity for item in cc_results),
|
|
204
|
+
"details": complexity_data
|
|
205
|
+
},
|
|
206
|
+
"maintainability_index": round(mi_score, 2) if mi_score else None,
|
|
207
|
+
"halstead": {
|
|
208
|
+
"difficulty": round(h_metrics.difficulty, 2) if h_metrics else None,
|
|
209
|
+
"volume": round(h_metrics.volume, 2) if h_metrics else None,
|
|
210
|
+
"effort": round(h_metrics.effort, 2) if h_metrics else None,
|
|
211
|
+
} if h_metrics else None
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
except ImportError:
|
|
215
|
+
# Radon not available, calculate basic cyclomatic complexity manually
|
|
216
|
+
return self._basic_complexity(code)
|
|
217
|
+
except Exception as e:
|
|
218
|
+
return {
|
|
219
|
+
"success": False,
|
|
220
|
+
"error": f"Failed to calculate complexity: {str(e)}"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
def _basic_complexity(self, code: str) -> Dict[str, Any]:
|
|
224
|
+
"""Calculate basic cyclomatic complexity without radon"""
|
|
225
|
+
try:
|
|
226
|
+
tree = ast.parse(code)
|
|
227
|
+
|
|
228
|
+
complexity_data = []
|
|
229
|
+
|
|
230
|
+
for node in ast.walk(tree):
|
|
231
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
232
|
+
complexity = self._calculate_function_complexity(node)
|
|
233
|
+
complexity_data.append({
|
|
234
|
+
"name": node.name,
|
|
235
|
+
"complexity": complexity,
|
|
236
|
+
"lineno": node.lineno,
|
|
237
|
+
"type": "function"
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
avg_complexity = sum(item["complexity"] for item in complexity_data) / len(complexity_data) if complexity_data else 0
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
"success": True,
|
|
244
|
+
"cyclomatic_complexity": {
|
|
245
|
+
"average": round(avg_complexity, 2),
|
|
246
|
+
"total": sum(item["complexity"] for item in complexity_data),
|
|
247
|
+
"details": complexity_data
|
|
248
|
+
},
|
|
249
|
+
"note": "Basic complexity calculation (radon not available)"
|
|
250
|
+
}
|
|
251
|
+
except Exception as e:
|
|
252
|
+
return {
|
|
253
|
+
"success": False,
|
|
254
|
+
"error": str(e)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
def _calculate_function_complexity(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> int:
|
|
258
|
+
"""Calculate cyclomatic complexity of a function"""
|
|
259
|
+
complexity = 1 # Base complexity
|
|
260
|
+
|
|
261
|
+
for child in ast.walk(node):
|
|
262
|
+
# Count decision points
|
|
263
|
+
if isinstance(child, (ast.If, ast.While, ast.For, ast.AsyncFor)):
|
|
264
|
+
complexity += 1
|
|
265
|
+
elif isinstance(child, ast.ExceptHandler):
|
|
266
|
+
complexity += 1
|
|
267
|
+
elif isinstance(child, ast.BoolOp):
|
|
268
|
+
complexity += len(child.values) - 1
|
|
269
|
+
|
|
270
|
+
return complexity
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class PythonExecutionTool:
|
|
274
|
+
"""
|
|
275
|
+
Tool for executing Python code in isolated environment.
|
|
276
|
+
This wraps the IsolatedExecutor for use by the agent.
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
def __init__(self, executor):
|
|
280
|
+
"""
|
|
281
|
+
Initialize with an executor instance.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
executor: IsolatedExecutor or SubprocessExecutor instance
|
|
285
|
+
"""
|
|
286
|
+
self.executor = executor
|
|
287
|
+
|
|
288
|
+
def execute(
|
|
289
|
+
self,
|
|
290
|
+
code: str,
|
|
291
|
+
description: str = "Execute Python code"
|
|
292
|
+
) -> Dict[str, Any]:
|
|
293
|
+
"""
|
|
294
|
+
Execute Python code and return results.
|
|
295
|
+
|
|
296
|
+
Args:
|
|
297
|
+
code: Python code to execute
|
|
298
|
+
description: Description of what's being executed
|
|
299
|
+
|
|
300
|
+
Returns:
|
|
301
|
+
Dictionary with execution results
|
|
302
|
+
"""
|
|
303
|
+
# Validate syntax first
|
|
304
|
+
is_valid, error = self.executor.validate_syntax(code)
|
|
305
|
+
if not is_valid:
|
|
306
|
+
return {
|
|
307
|
+
"success": False,
|
|
308
|
+
"error": error,
|
|
309
|
+
"description": description
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
# Execute code
|
|
313
|
+
result = self.executor.execute_code(code)
|
|
314
|
+
|
|
315
|
+
return {
|
|
316
|
+
"success": result.success,
|
|
317
|
+
"stdout": result.stdout,
|
|
318
|
+
"stderr": result.stderr,
|
|
319
|
+
"exit_code": result.exit_code,
|
|
320
|
+
"execution_time_ms": result.execution_time_ms,
|
|
321
|
+
"error": result.error_message,
|
|
322
|
+
"description": description
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
def execute_tests(
|
|
326
|
+
self,
|
|
327
|
+
test_code: str,
|
|
328
|
+
source_code: Optional[str] = None
|
|
329
|
+
) -> Dict[str, Any]:
|
|
330
|
+
"""
|
|
331
|
+
Execute pytest tests.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
test_code: Test code using pytest
|
|
335
|
+
source_code: Optional source code being tested
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
Dictionary with test execution results
|
|
339
|
+
"""
|
|
340
|
+
result = self.executor.execute_tests(test_code, source_code)
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
"success": result.success,
|
|
344
|
+
"stdout": result.stdout,
|
|
345
|
+
"stderr": result.stderr,
|
|
346
|
+
"exit_code": result.exit_code,
|
|
347
|
+
"execution_time_ms": result.execution_time_ms,
|
|
348
|
+
"error": result.error_message
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class FileOperationsTool:
|
|
353
|
+
"""
|
|
354
|
+
Tool for file operations (reading, writing, organizing outputs).
|
|
355
|
+
"""
|
|
356
|
+
|
|
357
|
+
def __init__(self, base_output_dir: Path):
|
|
358
|
+
"""
|
|
359
|
+
Initialize with base output directory.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
base_output_dir: Base directory for saving outputs
|
|
363
|
+
"""
|
|
364
|
+
self.base_output_dir = Path(base_output_dir)
|
|
365
|
+
self.base_output_dir.mkdir(parents=True, exist_ok=True)
|
|
366
|
+
|
|
367
|
+
def save_file(
|
|
368
|
+
self,
|
|
369
|
+
content: str,
|
|
370
|
+
filename: str,
|
|
371
|
+
subdirectory: Optional[str] = None
|
|
372
|
+
) -> Dict[str, Any]:
|
|
373
|
+
"""
|
|
374
|
+
Save content to a file.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
content: Content to save
|
|
378
|
+
filename: Name of the file
|
|
379
|
+
subdirectory: Optional subdirectory within base_output_dir
|
|
380
|
+
|
|
381
|
+
Returns:
|
|
382
|
+
Dictionary with file path and success status
|
|
383
|
+
"""
|
|
384
|
+
try:
|
|
385
|
+
if subdirectory:
|
|
386
|
+
output_dir = self.base_output_dir / subdirectory
|
|
387
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
388
|
+
else:
|
|
389
|
+
output_dir = self.base_output_dir
|
|
390
|
+
|
|
391
|
+
file_path = output_dir / filename
|
|
392
|
+
file_path.write_text(content)
|
|
393
|
+
|
|
394
|
+
return {
|
|
395
|
+
"success": True,
|
|
396
|
+
"file_path": str(file_path),
|
|
397
|
+
"absolute_path": str(file_path.absolute()),
|
|
398
|
+
"size_bytes": len(content.encode('utf-8'))
|
|
399
|
+
}
|
|
400
|
+
except Exception as e:
|
|
401
|
+
return {
|
|
402
|
+
"success": False,
|
|
403
|
+
"error": f"Failed to save file: {str(e)}"
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
def read_file(self, file_path: str) -> Dict[str, Any]:
|
|
407
|
+
"""
|
|
408
|
+
Read content from a file.
|
|
409
|
+
|
|
410
|
+
Args:
|
|
411
|
+
file_path: Path to the file
|
|
412
|
+
|
|
413
|
+
Returns:
|
|
414
|
+
Dictionary with file content and metadata
|
|
415
|
+
"""
|
|
416
|
+
try:
|
|
417
|
+
path = Path(file_path)
|
|
418
|
+
content = path.read_text()
|
|
419
|
+
|
|
420
|
+
return {
|
|
421
|
+
"success": True,
|
|
422
|
+
"content": content,
|
|
423
|
+
"size_bytes": len(content.encode('utf-8')),
|
|
424
|
+
"absolute_path": str(path.absolute())
|
|
425
|
+
}
|
|
426
|
+
except Exception as e:
|
|
427
|
+
return {
|
|
428
|
+
"success": False,
|
|
429
|
+
"error": f"Failed to read file: {str(e)}"
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
def save_multiple(
|
|
433
|
+
self,
|
|
434
|
+
files: Dict[str, str],
|
|
435
|
+
subdirectory: Optional[str] = None
|
|
436
|
+
) -> Dict[str, Any]:
|
|
437
|
+
"""
|
|
438
|
+
Save multiple files.
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
files: Dictionary of filename -> content
|
|
442
|
+
subdirectory: Optional subdirectory within base_output_dir
|
|
443
|
+
|
|
444
|
+
Returns:
|
|
445
|
+
Dictionary with results for each file
|
|
446
|
+
"""
|
|
447
|
+
results = {}
|
|
448
|
+
|
|
449
|
+
for filename, content in files.items():
|
|
450
|
+
result = self.save_file(content, filename, subdirectory)
|
|
451
|
+
results[filename] = result
|
|
452
|
+
|
|
453
|
+
success_count = sum(1 for r in results.values() if r.get("success"))
|
|
454
|
+
|
|
455
|
+
return {
|
|
456
|
+
"success": success_count == len(files),
|
|
457
|
+
"files": results,
|
|
458
|
+
"success_count": success_count,
|
|
459
|
+
"total_count": len(files)
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
def calculate_code_hash(code: str) -> str:
|
|
464
|
+
"""
|
|
465
|
+
Calculate SHA-256 hash of code.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
code: Source code
|
|
469
|
+
|
|
470
|
+
Returns:
|
|
471
|
+
Hexadecimal hash string
|
|
472
|
+
"""
|
|
473
|
+
return hashlib.sha256(code.encode('utf-8')).hexdigest()
|