Commit 8c8b4679 authored by Jan Reimes's avatar Jan Reimes
Browse files

docs(agents): add guidelines for agentic coding agents

* Introduced AGENTS.md with comprehensive guidelines for coding agents.
* Included project overview, build/lint/test commands, and quality gate.
* Defined code style guidelines, including naming conventions and error handling.
* Outlined provider architecture and environment variables for configuration.
parent a6eca4cb
Loading
Loading
Loading
Loading

AGENTS.md

0 → 100644
+170 −0
Original line number Diff line number Diff line
# AGENTS.md - Guidelines for Agentic Coding Agents

This document provides guidelines for agentic coding agents operating in this repository.

## Project Overview

PDF Remote Converter is a Python CLI tool and library that converts MS Office documents (Word, Excel, PowerPoint) to PDF using multiple cloud API providers (CloudConvert, Adobe PDF Services, Zamzar) with automatic failover and HTTP caching.

## Build/Lint/Test Commands

### Primary Commands

| Task | Command |
|------|---------|
| Install dependencies | `uv sync --dev` |
| Run all tests | `uv run pytest tests/ -v` |
| Run single test file | `uv run pytest tests/test_config.py -v` |
| Run single test function | `uv run pytest tests/test_config.py::test_adobe_requires_both_credentials -v` |
| Run tests with coverage | `uv run pytest tests/ -v --cov=pdf_remote_converter --cov-report=term-missing` |
| Lint check | `uv run ruff check src tests` |
| Lint fix | `uv run ruff check src tests --fix --unsafe-fixes` |
| Format check | `uv run ruff format --check src tests` |
| Format fix | `uv run ruff format src tests` |
| Type check | `uv run ty src` |
| Spell check | `uv run codespell src tests` |
| CLI help | `uv run pdf-remote-converter --help` |
| Convert document | `uv run pdf-remote-converter convert input.docx output.pdf` |

### Quality Gate (run before commit)

```bash
uv run ruff check src tests && uv run ruff format --check src tests && uv run pytest tests/ -v --cov=pdf_remote_converter --cov-report=term-missing
```

## Project Structure

The project structure can be parsed using the following command from the root of the repository:

```shell
rg --files | tree-cli --fromfile
```

Notes:

- Command requires `ripgrep` and `tree-cli` tools, which can be installed in the project via: `mise up`.
- Files/folders are never listed in the present file, always generate the structure on the fly using the above command!

## Code Style Guidelines

### Python Version

- Target: Python 3.13+
- Use modern type syntax: `list[str]` not `List[str]`, `str | None` not `Optional[str]`

### Imports

- All imports must be at the top of the file (PLC0415 is enforced)
- Import order (enforced by ruff/isort):
  1. Standard library
  2. Third-party packages
  3. First-party (`pdf_remote_converter`)
- Known first-party package: `pdf_remote_converter`

### Type Annotations

- Required on all function parameters and return types (ANN001, ANN202 enforced)
- Use `from __future__ import annotations` for modern type syntax
- Use `ValidationInfo` from pydantic for validator signatures

### Formatting

- Line length: 160 characters
- Docstring convention: Google style
- Docstring code blocks: formatted with same line length

### Naming Conventions

- Classes: PascalCase (e.g., `CloudConvertProvider`, `ConversionResult`)
- Functions/methods: snake_case (e.g., `get_configured_providers`, `convert_with_failover`)
- Private functions: prefix with underscore (e.g., `_compute_file_hash`)
- Constants: UPPER_SNAKE_CASE (e.g., `PROVIDER_PREFERENCE`)
- Module-level singletons: PascalCase or UPPER_SNAKE_CASE

### Error Handling

- Use custom exceptions from `pdf_remote_converter.exceptions`:
  - `QuotaExceededError` - provider quota exhausted
  - `RateLimitError` - rate limited by provider
  - `ProviderUnavailableError` - provider service down
  - `AuthenticationError` - invalid API credentials
  - `NoProviderConfiguredError` - no API keys set
  - `AllProvidersFailedError` - all providers failed
- Use `raise ... from e` to preserve exception chain

### Data Classes

- Use `@dataclass` for simple data containers
- Use Pydantic models for configuration and API responses

### Protocol Classes

- Use `typing.Protocol` for interfaces (see `ProviderBackend` in `providers/base.py`)
- Protocol methods without default implementations use `...` (ellipsis)

### Logging

- Use standard `logging` module
- Format: `%(asctime)s [%(levelname)s] %(name)s: %(message)s`
- Log to stderr
- Use `--verbose` flag for DEBUG level

## Provider Architecture

### Provider Protocol

All providers implement `ProviderBackend` protocol:

```python
class ProviderBackend(Protocol):
    name: str
    supported_formats: set[str]
    monthly_quota: int
    quota_remaining: int
    
    def convert(self, input_path: Path, output_path: Path) -> ConversionResult: ...
    def is_healthy(self) -> bool: ...
```

### Provider Preference Order

1. CloudConvert (default, 10/day free tier)
2. Adobe PDF Services (500/month free tier)
3. Zamzar (100/month free tier, 1MB limit)

### Failover Behavior

- Automatic failover on: `QuotaExceededError`, `RateLimitError`, `ProviderUnavailableError`
- No failover on: authentication errors, invalid format, file too large

## Environment Variables

| Variable | Description |
|----------|-------------|
| `CLOUDCONVERT_API_KEY` | CloudConvert API key |
| `ADOBE_CLIENT_ID` | Adobe client ID |
| `ADOBE_CLIENT_SECRET` | Adobe client secret |
| `ZAMZAR_API_KEY` | Zamzar API key |
| `PDF_REMOTE_CONVERTER_API_KEY` | Generic fallback API key |
| `PDF_REMOTE_CONVERTER_DEFAULT_PROVIDER` | Default provider (default: cloudconvert) |
| `PDF_REMOTE_CONVERTER_CACHE_DIR` | Cache directory (default: ~/.cache/pdf-remote-converter) |

## Test Guidelines

- 100% coverage required (`fail_under = 100` in pytest-cov)
- Use `pytest.Monkeypatch` for environment variable manipulation
- Use `pytest.LogCaptureFixture` for log testing
- Mock providers available in `tests/conftest.py`
- Test path: `tests/` with pythonpath including `src` and `tests`

## Key Files

| File | Purpose |
|------|---------|
| `src/pdf_remote_converter/config.py` | Pydantic settings, env var loading |
| `src/pdf_remote_converter/exceptions.py` | Custom exception classes |
| `src/pdf_remote_converter/http.py` | Hishel-cached httpx client factory |
| `src/pdf_remote_converter/router.py` | Provider selection and failover |
| `src/pdf_remote_converter/converter.py` | High-level Converter facade |
| `src/pdf_remote_converter/providers/base.py` | Provider protocol definition |
| `src/pdf_remote_converter/providers/models.py` | Conversion result models |