Files
microdao-daarion/providers/devtools_provider.py
Ivan Tytar 3cacf67cf5 feat: Initial commit - DAGI Stack v0.2.0 (Phase 2 Complete)
- Router Core with rule-based routing (1530 lines)
- DevTools Backend (file ops, test execution) (393 lines)
- CrewAI Orchestrator (4 workflows, 12 agents) (358 lines)
- Bot Gateway (Telegram/Discord) (321 lines)
- RBAC Service (role resolution) (272 lines)
- Structured logging (utils/logger.py)
- Docker deployment (docker-compose.yml)
- Comprehensive documentation (57KB)
- Test suites (41 tests, 95% coverage)
- Phase 4 roadmap & ecosystem integration plans

Production-ready infrastructure for DAARION microDAOs.
2025-11-15 14:35:24 +01:00

132 lines
4.1 KiB
Python

"""
DevTools Provider
Calls a DevTools backend over HTTP for development operations:
- fs_read, fs_write
- run_tests
- notebook_execute
"""
import logging
from typing import Dict, Any, Optional
import httpx
from providers.base import Provider
from router_models import RouterRequest, RouterResponse
logger = logging.getLogger(__name__)
class DevToolsProvider(Provider):
"""
Provider that routes requests to a DevTools backend service.
The backend implements tools for:
- File system operations (read/write)
- CI operations (run tests)
- Notebook execution
- Git operations (future)
"""
def __init__(
self,
provider_id: str,
base_url: str,
timeout: int = 30,
**kwargs
):
super().__init__(provider_id)
self.base_url = base_url.rstrip("/")
self.timeout = timeout
logger.info(f"DevToolsProvider initialized: {provider_id}{base_url}")
async def call(self, request: RouterRequest) -> RouterResponse:
"""
Route request to DevTools backend.
Expected request.payload format:
{
"tool": "fs_read" | "fs_write" | "run_tests" | "notebook_execute",
"params": {...}
}
"""
try:
# Extract tool and params from payload
tool = request.payload.get("tool") if request.payload else None
if not tool:
return RouterResponse(
ok=False,
provider_id=self.id,
error="Missing 'tool' in request payload"
)
params = request.payload.get("params", {}) if request.payload else {}
# Map tool to endpoint
endpoint_map = {
"fs_read": "/fs/read",
"fs_write": "/fs/write",
"run_tests": "/ci/run-tests",
"notebook_execute": "/notebook/execute",
}
endpoint = endpoint_map.get(tool)
if not endpoint:
return RouterResponse(
ok=False,
provider_id=self.id,
error=f"Unknown tool: {tool}. Available: {list(endpoint_map.keys())}"
)
# Build request body
body = {
"dao_id": request.dao_id,
"user_id": request.user_id,
"source": request.source,
**params
}
# Call backend
url = f"{self.base_url}{endpoint}"
logger.info(f"DevTools call: {tool}{url}")
async with httpx.AsyncClient(timeout=self.timeout) as client:
response = await client.post(url, json=body)
response.raise_for_status()
data = response.json()
return RouterResponse(
ok=True,
provider_id=self.id,
data=data,
metadata={
"provider_type": "devtools",
"tool": tool,
"endpoint": endpoint,
"status_code": response.status_code
}
)
except httpx.HTTPStatusError as e:
logger.error(f"DevTools HTTP error: {e}")
return RouterResponse(
ok=False,
provider_id=self.id,
error=f"HTTP {e.response.status_code}: {e.response.text}"
)
except httpx.RequestError as e:
logger.error(f"DevTools request error: {e}")
return RouterResponse(
ok=False,
provider_id=self.id,
error=f"Request failed: {str(e)}"
)
except Exception as e:
logger.error(f"DevTools error: {e}")
return RouterResponse(
ok=False,
provider_id=self.id,
error=str(e)
)