# 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`:

```python
{
    "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:**
```json
{
    "action": "tree",
    "path": "services",
    "depth": 2
}
```

**Response:**
```json
{
    "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:**
```json
{
    "action": "read",
    "path": "services/router/main.py",
    "start_line": 1,
    "end_line": 50
}
```

**Response:**
```json
{
    "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:**
```json
{
    "action": "search",
    "query": "async def",
    "path": "services",
    "glob": "**/*.py",
    "limit": 20
}
```

**Response:**
```json
{
    "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:**
```json
{
    "action": "metadata",
    "path": "."
}
```

**Response:**
```json
{
    "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

```json
{
    "success": false,
    "result": null,
    "error": "Path traversal detected. Access denied."
}
```

```json
{
    "success": false,
    "result": null,
    "error": "File too large: 500000 bytes (max: 204800)"
}
```

## Testing

Run tests:
```bash
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
