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,127 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CodeInterpreterTool - Agent-as-Tool for comprehensive code analysis.
|
|
3
|
+
|
|
4
|
+
This package provides a Parrot Tool for analyzing, documenting,
|
|
5
|
+
testing, debugging, and explaining Python code.
|
|
6
|
+
|
|
7
|
+
Main components:
|
|
8
|
+
- CodeInterpreterTool: Main Parrot tool class (inherits from AbstractTool)
|
|
9
|
+
- Response models: Pydantic models for structured outputs
|
|
10
|
+
- Isolated execution: Docker-based code execution environment
|
|
11
|
+
- Internal tools: Static analysis, execution, and file operations
|
|
12
|
+
|
|
13
|
+
Quick start:
|
|
14
|
+
>>> from parrot.tools.code_interpreter import CodeInterpreterTool
|
|
15
|
+
>>> from your_llm_client import LLMClient
|
|
16
|
+
>>>
|
|
17
|
+
>>> client = LLMClient(api_key="your-key")
|
|
18
|
+
>>> tool = CodeInterpreterTool(llm=client)
|
|
19
|
+
>>>
|
|
20
|
+
>>> # Use as async tool
|
|
21
|
+
>>> result = await tool._execute(
|
|
22
|
+
... code=source_code,
|
|
23
|
+
... operation="analyze"
|
|
24
|
+
... )
|
|
25
|
+
>>> print(result)
|
|
26
|
+
|
|
27
|
+
>>> # Or use convenience methods
|
|
28
|
+
>>> analysis = await tool.analyze_code(source_code)
|
|
29
|
+
>>> print(analysis.executive_summary)
|
|
30
|
+
"""
|
|
31
|
+
from .tool import CodeInterpreterTool, CodeInterpreterArgs
|
|
32
|
+
# Import response models
|
|
33
|
+
from .models import (
|
|
34
|
+
# Enums
|
|
35
|
+
OperationType,
|
|
36
|
+
ExecutionStatus,
|
|
37
|
+
Severity,
|
|
38
|
+
DocstringFormat,
|
|
39
|
+
TestType,
|
|
40
|
+
|
|
41
|
+
# Base models
|
|
42
|
+
BaseCodeResponse,
|
|
43
|
+
CodeReference,
|
|
44
|
+
|
|
45
|
+
# Response models
|
|
46
|
+
CodeAnalysisResponse,
|
|
47
|
+
DocumentationResponse,
|
|
48
|
+
TestGenerationResponse,
|
|
49
|
+
DebugResponse,
|
|
50
|
+
ExplanationResponse,
|
|
51
|
+
|
|
52
|
+
# Component models
|
|
53
|
+
ComplexityMetrics,
|
|
54
|
+
FunctionComponent,
|
|
55
|
+
ClassComponent,
|
|
56
|
+
Dependency,
|
|
57
|
+
QualityObservation,
|
|
58
|
+
DocumentedElement,
|
|
59
|
+
GeneratedTest,
|
|
60
|
+
CoverageGap,
|
|
61
|
+
BugIssue,
|
|
62
|
+
CodeFlowStep,
|
|
63
|
+
ConceptExplanation,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
# Import executors
|
|
67
|
+
from .executor import (
|
|
68
|
+
IsolatedExecutor,
|
|
69
|
+
SubprocessExecutor,
|
|
70
|
+
ExecutionResult,
|
|
71
|
+
create_executor,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Import internal tools
|
|
75
|
+
from .internals import (
|
|
76
|
+
StaticAnalysisTool,
|
|
77
|
+
PythonExecutionTool,
|
|
78
|
+
FileOperationsTool,
|
|
79
|
+
calculate_code_hash,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
__all__ = [
|
|
83
|
+
# Main Parrot tool
|
|
84
|
+
"CodeInterpreterTool",
|
|
85
|
+
"CodeInterpreterArgs",
|
|
86
|
+
|
|
87
|
+
# Enums
|
|
88
|
+
"OperationType",
|
|
89
|
+
"ExecutionStatus",
|
|
90
|
+
"Severity",
|
|
91
|
+
"DocstringFormat",
|
|
92
|
+
"TestType",
|
|
93
|
+
|
|
94
|
+
# Response models
|
|
95
|
+
"CodeAnalysisResponse",
|
|
96
|
+
"DocumentationResponse",
|
|
97
|
+
"TestGenerationResponse",
|
|
98
|
+
"DebugResponse",
|
|
99
|
+
"ExplanationResponse",
|
|
100
|
+
|
|
101
|
+
# Component models
|
|
102
|
+
"BaseCodeResponse",
|
|
103
|
+
"CodeReference",
|
|
104
|
+
"ComplexityMetrics",
|
|
105
|
+
"FunctionComponent",
|
|
106
|
+
"ClassComponent",
|
|
107
|
+
"Dependency",
|
|
108
|
+
"QualityObservation",
|
|
109
|
+
"DocumentedElement",
|
|
110
|
+
"GeneratedTest",
|
|
111
|
+
"CoverageGap",
|
|
112
|
+
"BugIssue",
|
|
113
|
+
"CodeFlowStep",
|
|
114
|
+
"ConceptExplanation",
|
|
115
|
+
|
|
116
|
+
# Executors
|
|
117
|
+
"IsolatedExecutor",
|
|
118
|
+
"SubprocessExecutor",
|
|
119
|
+
"ExecutionResult",
|
|
120
|
+
"create_executor",
|
|
121
|
+
|
|
122
|
+
# Internal tools
|
|
123
|
+
"StaticAnalysisTool",
|
|
124
|
+
"PythonExecutionTool",
|
|
125
|
+
"FileOperationsTool",
|
|
126
|
+
"calculate_code_hash",
|
|
127
|
+
]
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Isolated code execution environment using Docker containers.
|
|
3
|
+
Provides secure Python code execution with resource limits and timeout controls.
|
|
4
|
+
"""
|
|
5
|
+
import time
|
|
6
|
+
from typing import Dict, Any, Optional, Tuple
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
import tempfile
|
|
10
|
+
import docker
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class ExecutionResult:
|
|
15
|
+
"""Result from code execution in isolated environment"""
|
|
16
|
+
success: bool
|
|
17
|
+
stdout: str
|
|
18
|
+
stderr: str
|
|
19
|
+
exit_code: int
|
|
20
|
+
execution_time_ms: int
|
|
21
|
+
error_message: Optional[str] = None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class IsolatedExecutor:
|
|
25
|
+
"""
|
|
26
|
+
Manages isolated Python code execution using Docker containers.
|
|
27
|
+
|
|
28
|
+
Features:
|
|
29
|
+
- Resource limits (memory, CPU)
|
|
30
|
+
- Execution timeout
|
|
31
|
+
- Network isolation
|
|
32
|
+
- Read-only filesystem (except work directory)
|
|
33
|
+
- Container reuse for better performance
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
image: str = "python:3.11-alpine",
|
|
39
|
+
memory_limit: str = "512m",
|
|
40
|
+
cpu_quota: int = 50000, # 50% of one CPU
|
|
41
|
+
timeout_seconds: int = 30,
|
|
42
|
+
enable_network: bool = False,
|
|
43
|
+
):
|
|
44
|
+
"""
|
|
45
|
+
Initialize the isolated executor.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
image: Docker image to use for execution
|
|
49
|
+
memory_limit: Memory limit (e.g., "512m", "1g")
|
|
50
|
+
cpu_quota: CPU quota in microseconds per 100ms period
|
|
51
|
+
timeout_seconds: Maximum execution time in seconds
|
|
52
|
+
enable_network: Whether to allow network access
|
|
53
|
+
"""
|
|
54
|
+
self.client = docker.from_env()
|
|
55
|
+
self.image = image
|
|
56
|
+
self.memory_limit = memory_limit
|
|
57
|
+
self.cpu_quota = cpu_quota
|
|
58
|
+
self.cpu_period = 100000 # Standard 100ms period
|
|
59
|
+
self.timeout_seconds = timeout_seconds
|
|
60
|
+
self.enable_network = enable_network
|
|
61
|
+
|
|
62
|
+
# Ensure image is available
|
|
63
|
+
self._ensure_image()
|
|
64
|
+
|
|
65
|
+
def _ensure_image(self):
|
|
66
|
+
"""Ensure the Docker image is available locally"""
|
|
67
|
+
try:
|
|
68
|
+
self.client.images.get(self.image)
|
|
69
|
+
except docker.errors.ImageNotFound:
|
|
70
|
+
print(f"Pulling Docker image: {self.image}")
|
|
71
|
+
self.client.images.pull(self.image)
|
|
72
|
+
|
|
73
|
+
def execute_code(
|
|
74
|
+
self,
|
|
75
|
+
code: str,
|
|
76
|
+
working_dir: Optional[Path] = None,
|
|
77
|
+
additional_files: Optional[Dict[str, str]] = None,
|
|
78
|
+
) -> ExecutionResult:
|
|
79
|
+
"""
|
|
80
|
+
Execute Python code in an isolated Docker container.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
code: Python code to execute
|
|
84
|
+
working_dir: Optional directory to mount as working directory
|
|
85
|
+
additional_files: Optional dict of filename -> content to create
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
ExecutionResult with execution details
|
|
89
|
+
"""
|
|
90
|
+
start_time = time.time()
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
# Create temporary directory for code execution
|
|
94
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
95
|
+
temp_path = Path(temp_dir)
|
|
96
|
+
|
|
97
|
+
# Write the main code file
|
|
98
|
+
code_file = temp_path / "main.py"
|
|
99
|
+
code_file.write_text(code)
|
|
100
|
+
|
|
101
|
+
# Write additional files if provided
|
|
102
|
+
if additional_files:
|
|
103
|
+
for filename, content in additional_files.items():
|
|
104
|
+
file_path = temp_path / filename
|
|
105
|
+
file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
106
|
+
file_path.write_text(content)
|
|
107
|
+
|
|
108
|
+
# Prepare container configuration
|
|
109
|
+
container_config = {
|
|
110
|
+
"image": self.image,
|
|
111
|
+
"command": ["python", "/workspace/main.py"],
|
|
112
|
+
"volumes": {
|
|
113
|
+
str(temp_path): {"bind": "/workspace", "mode": "rw"}
|
|
114
|
+
},
|
|
115
|
+
"working_dir": "/workspace",
|
|
116
|
+
"mem_limit": self.memory_limit,
|
|
117
|
+
"cpu_quota": self.cpu_quota,
|
|
118
|
+
"cpu_period": self.cpu_period,
|
|
119
|
+
"network_disabled": not self.enable_network,
|
|
120
|
+
"detach": True,
|
|
121
|
+
"remove": True, # Auto-remove container after execution
|
|
122
|
+
"user": "nobody", # Run as unprivileged user
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Add working directory mount if provided
|
|
126
|
+
if working_dir and working_dir.exists():
|
|
127
|
+
container_config["volumes"][str(working_dir)] = {
|
|
128
|
+
"bind": "/workdir",
|
|
129
|
+
"mode": "ro" # Read-only mount
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Run container
|
|
133
|
+
container = self.client.containers.run(**container_config)
|
|
134
|
+
|
|
135
|
+
# Wait for completion with timeout
|
|
136
|
+
try:
|
|
137
|
+
result = container.wait(timeout=self.timeout_seconds)
|
|
138
|
+
exit_code = result["StatusCode"]
|
|
139
|
+
|
|
140
|
+
# Get output
|
|
141
|
+
stdout = container.logs(stdout=True, stderr=False).decode("utf-8")
|
|
142
|
+
stderr = container.logs(stdout=False, stderr=True).decode("utf-8")
|
|
143
|
+
|
|
144
|
+
execution_time = int((time.time() - start_time) * 1000)
|
|
145
|
+
|
|
146
|
+
return ExecutionResult(
|
|
147
|
+
success=(exit_code == 0),
|
|
148
|
+
stdout=stdout,
|
|
149
|
+
stderr=stderr,
|
|
150
|
+
exit_code=exit_code,
|
|
151
|
+
execution_time_ms=execution_time,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
except docker.errors.APIError as e:
|
|
155
|
+
# Timeout or other container error
|
|
156
|
+
try:
|
|
157
|
+
container.stop(timeout=1)
|
|
158
|
+
container.remove(force=True)
|
|
159
|
+
except:
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
execution_time = int((time.time() - start_time) * 1000)
|
|
163
|
+
|
|
164
|
+
return ExecutionResult(
|
|
165
|
+
success=False,
|
|
166
|
+
stdout="",
|
|
167
|
+
stderr="",
|
|
168
|
+
exit_code=-1,
|
|
169
|
+
execution_time_ms=execution_time,
|
|
170
|
+
error_message=f"Execution timeout after {self.timeout_seconds}s or container error: {str(e)}",
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
except Exception as e:
|
|
174
|
+
execution_time = int((time.time() - start_time) * 1000)
|
|
175
|
+
return ExecutionResult(
|
|
176
|
+
success=False,
|
|
177
|
+
stdout="",
|
|
178
|
+
stderr="",
|
|
179
|
+
exit_code=-1,
|
|
180
|
+
execution_time_ms=execution_time,
|
|
181
|
+
error_message=f"Failed to execute code: {str(e)}",
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def execute_tests(
|
|
185
|
+
self,
|
|
186
|
+
test_code: str,
|
|
187
|
+
source_code: Optional[str] = None,
|
|
188
|
+
requirements: Optional[list[str]] = None,
|
|
189
|
+
) -> ExecutionResult:
|
|
190
|
+
"""
|
|
191
|
+
Execute pytest tests in isolated environment.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
test_code: Test code using pytest
|
|
195
|
+
source_code: Optional source code being tested
|
|
196
|
+
requirements: Optional list of pip packages to install
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
ExecutionResult with test execution details
|
|
200
|
+
"""
|
|
201
|
+
# Prepare setup script to install pytest and requirements
|
|
202
|
+
setup_commands = ["pip install -q pytest"]
|
|
203
|
+
if requirements:
|
|
204
|
+
setup_commands.extend([f"pip install -q {req}" for req in requirements])
|
|
205
|
+
|
|
206
|
+
# Create wrapper script that installs deps and runs tests
|
|
207
|
+
wrapper_code = f"""
|
|
208
|
+
import subprocess
|
|
209
|
+
import sys
|
|
210
|
+
|
|
211
|
+
# Install dependencies
|
|
212
|
+
setup_commands = {setup_commands}
|
|
213
|
+
for cmd in setup_commands:
|
|
214
|
+
result = subprocess.run(cmd.split(), capture_output=True)
|
|
215
|
+
if result.returncode != 0:
|
|
216
|
+
print(f"Failed to install dependency: {{cmd}}", file=sys.stderr)
|
|
217
|
+
print(result.stderr.decode(), file=sys.stderr)
|
|
218
|
+
sys.exit(1)
|
|
219
|
+
|
|
220
|
+
# Run pytest
|
|
221
|
+
result = subprocess.run(
|
|
222
|
+
["pytest", "-v", "/workspace/test_main.py"],
|
|
223
|
+
capture_output=True,
|
|
224
|
+
text=True
|
|
225
|
+
)
|
|
226
|
+
print(result.stdout)
|
|
227
|
+
if result.stderr:
|
|
228
|
+
print(result.stderr, file=sys.stderr)
|
|
229
|
+
sys.exit(result.returncode)
|
|
230
|
+
"""
|
|
231
|
+
|
|
232
|
+
# Prepare additional files
|
|
233
|
+
additional_files = {"test_main.py": test_code}
|
|
234
|
+
if source_code:
|
|
235
|
+
additional_files["source.py"] = source_code
|
|
236
|
+
|
|
237
|
+
return self.execute_code(
|
|
238
|
+
code=wrapper_code,
|
|
239
|
+
additional_files=additional_files,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
def validate_syntax(self, code: str) -> Tuple[bool, Optional[str]]:
|
|
243
|
+
"""
|
|
244
|
+
Validate Python syntax without executing.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
code: Python code to validate
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Tuple of (is_valid, error_message)
|
|
251
|
+
"""
|
|
252
|
+
try:
|
|
253
|
+
compile(code, "<string>", "exec")
|
|
254
|
+
return True, None
|
|
255
|
+
except SyntaxError as e:
|
|
256
|
+
return False, f"Syntax error at line {e.lineno}: {e.msg}"
|
|
257
|
+
except Exception as e:
|
|
258
|
+
return False, f"Validation error: {str(e)}"
|
|
259
|
+
|
|
260
|
+
def cleanup(self):
|
|
261
|
+
"""Clean up Docker resources"""
|
|
262
|
+
try:
|
|
263
|
+
# Remove any dangling containers from this executor
|
|
264
|
+
self.client.containers.prune()
|
|
265
|
+
except Exception as e:
|
|
266
|
+
print(f"Cleanup warning: {e}")
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# Subprocess-based fallback for environments without Docker
|
|
270
|
+
class SubprocessExecutor:
|
|
271
|
+
"""
|
|
272
|
+
Fallback executor using subprocess with basic restrictions.
|
|
273
|
+
WARNING: Less secure than Docker-based isolation.
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
def __init__(self, timeout_seconds: int = 30):
|
|
277
|
+
self.timeout_seconds = timeout_seconds
|
|
278
|
+
|
|
279
|
+
def execute_code(
|
|
280
|
+
self,
|
|
281
|
+
code: str,
|
|
282
|
+
working_dir: Optional[Path] = None,
|
|
283
|
+
additional_files: Optional[Dict[str, str]] = None,
|
|
284
|
+
) -> ExecutionResult:
|
|
285
|
+
"""Execute code using subprocess"""
|
|
286
|
+
import subprocess
|
|
287
|
+
|
|
288
|
+
start_time = time.time()
|
|
289
|
+
|
|
290
|
+
try:
|
|
291
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
292
|
+
temp_path = Path(temp_dir)
|
|
293
|
+
code_file = temp_path / "main.py"
|
|
294
|
+
code_file.write_text(code)
|
|
295
|
+
|
|
296
|
+
if additional_files:
|
|
297
|
+
for filename, content in additional_files.items():
|
|
298
|
+
(temp_path / filename).write_text(content)
|
|
299
|
+
|
|
300
|
+
result = subprocess.run(
|
|
301
|
+
["python", str(code_file)],
|
|
302
|
+
cwd=temp_path,
|
|
303
|
+
capture_output=True,
|
|
304
|
+
text=True,
|
|
305
|
+
timeout=self.timeout_seconds,
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
execution_time = int((time.time() - start_time) * 1000)
|
|
309
|
+
|
|
310
|
+
return ExecutionResult(
|
|
311
|
+
success=(result.returncode == 0),
|
|
312
|
+
stdout=result.stdout,
|
|
313
|
+
stderr=result.stderr,
|
|
314
|
+
exit_code=result.returncode,
|
|
315
|
+
execution_time_ms=execution_time,
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
except subprocess.TimeoutExpired:
|
|
319
|
+
execution_time = int((time.time() - start_time) * 1000)
|
|
320
|
+
return ExecutionResult(
|
|
321
|
+
success=False,
|
|
322
|
+
stdout="",
|
|
323
|
+
stderr="",
|
|
324
|
+
exit_code=-1,
|
|
325
|
+
execution_time_ms=execution_time,
|
|
326
|
+
error_message=f"Execution timeout after {self.timeout_seconds}s",
|
|
327
|
+
)
|
|
328
|
+
except Exception as e:
|
|
329
|
+
execution_time = int((time.time() - start_time) * 1000)
|
|
330
|
+
return ExecutionResult(
|
|
331
|
+
success=False,
|
|
332
|
+
stdout="",
|
|
333
|
+
stderr="",
|
|
334
|
+
exit_code=-1,
|
|
335
|
+
execution_time_ms=execution_time,
|
|
336
|
+
error_message=str(e),
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
def validate_syntax(self, code: str) -> Tuple[bool, Optional[str]]:
|
|
340
|
+
"""Validate Python syntax"""
|
|
341
|
+
try:
|
|
342
|
+
compile(code, "<string>", "exec")
|
|
343
|
+
return True, None
|
|
344
|
+
except SyntaxError as e:
|
|
345
|
+
return False, f"Syntax error at line {e.lineno}: {e.msg}"
|
|
346
|
+
except Exception as e:
|
|
347
|
+
return False, f"Validation error: {str(e)}"
|
|
348
|
+
|
|
349
|
+
def cleanup(self):
|
|
350
|
+
"""No cleanup needed for subprocess executor"""
|
|
351
|
+
pass
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def create_executor(use_docker: bool = True, **kwargs) -> IsolatedExecutor | SubprocessExecutor:
|
|
355
|
+
"""
|
|
356
|
+
Factory function to create appropriate executor.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
use_docker: Whether to use Docker (falls back to subprocess if Docker unavailable)
|
|
360
|
+
**kwargs: Additional arguments for executor
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
Executor instance
|
|
364
|
+
"""
|
|
365
|
+
if not use_docker:
|
|
366
|
+
return SubprocessExecutor(timeout_seconds=kwargs.get("timeout_seconds", 30))
|
|
367
|
+
try:
|
|
368
|
+
return IsolatedExecutor(**kwargs)
|
|
369
|
+
except Exception as e:
|
|
370
|
+
print(f"Docker not available: {e}. Falling back to subprocess executor.")
|
|
371
|
+
return SubprocessExecutor(timeout_seconds=kwargs.get("timeout_seconds", 30))
|