Config policies (16 files): alert_routing, architecture_pressure, backlog, cost_weights, data_governance, incident_escalation, incident_intelligence, network_allowlist, nodes_registry, observability_sources, rbac_tools_matrix, release_gate, risk_attribution, risk_policy, slo_policy, tool_limits, tools_rollout Ops (22 files): Caddyfile, calendar compose, grafana voice dashboard, deployments/incidents logs, runbooks for alerts/audit/backlog/incidents/sofiia/voice, cron jobs, scripts (alert_triage, audit_cleanup, migrate_*, governance, schedule), task_registry, voice alerts/ha/latency/policy Docs (30+ files): HUMANIZED_STEPAN v2.7-v3 changelogs and runbooks, NODA1/NODA2 status and setup, audit index and traces, backlog, incident, supervisor, tools, voice, opencode, release, risk, aistalk, spacebot Made-with: Cursor
5.6 KiB
RepoTool - Read-only Repository Access
Overview
RepoTool provides read-only access to the DAARION repository filesystem for agents (primarily Sofiia). It allows viewing code, configs, and searching through the codebase without any write or execute capabilities.
Integration
Tool Definition
RepoTool is registered in services/router/tool_manager.py under TOOL_DEFINITIONS:
{
"type": "function",
"function": {
"name": "repo_tool",
"description": "📂 Read-only доступ до файловї системи репозиторію...",
"parameters": {
"type": "object",
"properties": {
"action": {
"type": "string",
"enum": ["tree", "read", "search", "metadata"]
},
"path": {"type": "string"},
"start_line": {"type": "integer"},
"end_line": {"type": "integer"},
"depth": {"type": "integer"},
"glob": {"type": "string"},
"query": {"type": "string"},
"limit": {"type": "integer"},
"max_bytes": {"type": "integer"}
},
"required": ["action"]
}
}
}
RBAC Configuration
Added to services/router/agent_tools_config.py in FULL_STANDARD_STACK - available to all agents.
Actions
1. tree - Directory Structure
Show directory tree starting from a path.
Parameters:
path: Starting path (default: ".")depth: Maximum depth (default: 3, max: 10)glob: Optional glob pattern to filter files
Example:
{
"action": "tree",
"path": "services",
"depth": 2
}
Response:
{
"success": true,
"result": {
"tree": {
"router": {"main.py": "[file]", "tool_manager.py": "[file]"},
"gateway": {"main.py": "[file]"}
},
"path": "services"
}
}
2. read - File Content
Read file contents with optional line limits.
Parameters:
path: File path (required)start_line: Starting line (default: 1)end_line: Ending line (optional)max_bytes: Max bytes to read (default: 200KB, max: 1MB)
Example:
{
"action": "read",
"path": "services/router/main.py",
"start_line": 1,
"end_line": 50
}
Response:
{
"success": true,
"result": {
"path": "services/router/main.py",
"content": "import asyncio\n...",
"lines": 50,
"start_line": 1,
"end_line": 50
}
}
3. search - Text Search
Search for text in files using grep.
Parameters:
query: Search query (required)path: Starting path (default: ".")glob: File pattern (e.g., "**/*.py")limit: Max results (default: 50, max: 200)
Example:
{
"action": "search",
"query": "async def",
"path": "services",
"glob": "**/*.py",
"limit": 20
}
Response:
{
"success": true,
"result": {
"query": "async def",
"path": "services",
"matches": [
{"file": "router/main.py", "line": "45", "content": "async def handle_request"},
{"file": "router/main.py", "line": "102", "content": "async def process_message"}
],
"count": 2
}
}
4. metadata - Git Information
Get git repository metadata.
Parameters:
path: Path within repo (optional)
Example:
{
"action": "metadata",
"path": "."
}
Response:
{
"success": true,
"result": {
"path": ".",
"repo_root": "/path/to/repo",
"commit": "abc123def456",
"branch": "main",
"dirty": false
}
}
Security Features
Path Traversal Protection
- Blocks
..in paths - Rejects absolute paths outside repo root
- Validates resolved path stays within repo root
Symlink Escape Prevention
- Uses
os.path.realpath()to resolve symlinks - Ensures resolved path is still within repo root
- Blocks access through symlinks to external locations
Secret Masking
Files and content containing secrets are automatically masked:
Masked file patterns:
.env,.env.local,.env.production*secrets*,*credentials*,*keys*,*tokens*,*passwords*
Masked content patterns:
api_key = xxx → api_key = ***
token = xxx → token = ***
password = xxx → password = ***
SECRET_KEY=xxx → SECRET_KEY=***
Bearer xxx → Bearer ***
-----BEGIN PRIVATE KEY----- → [MASKED]
Limits
| Limit | Default | Max |
|---|---|---|
| Tree depth | 3 | 10 |
| Search results | 50 | 200 |
| File size | 200KB | 1MB |
| Lines per read | 1000 | - |
| Search timeout | - | 10s |
Example Usage
Sofiia Commands
"Покажи структуру папки services"
"Прочитай файл services/router/main.py перші 50 рядків"
"Знайди всі файли з 'async def' в папці services"
"Який останній коміт?"
Error Responses
{
"success": false,
"result": null,
"error": "Path traversal detected. Access denied."
}
{
"success": false,
"result": null,
"error": "File too large: 500000 bytes (max: 204800)"
}
Testing
Run tests:
cd /path/to/repo
pytest tools/repo_tool/tests/test_repo_tool.py -v
Test coverage:
- Path traversal blocked
- Symlink escape blocked
- Absolute path blocked
- Tree action works
- Read action works with line limits
- Search finds content
- Metadata returns git info
- Secret files (.env) masked
- Inline secrets masked
- Size limits enforced
- Depth limits enforced