diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 81d5e1a4..157c666e 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -20,8 +20,10 @@ What else did you try or consider? Why is the proposal preferable? ## Scope notes -- Is this a new role/component in the chain (RequestProcessor / LLMBackend / ResponseProcessor / ResponseTranslator), or an extension of an existing one? -- Does it touch a public API listed in `switchyard/__init__.py.__all__`? +- Which surface owns the change: server API or configuration, routing algorithm, + protocol type, translation codec, upstream client, skill-distillation contract, + Python binding, or launcher? +- Does it change a public Rust, PyO3, Python, CLI, or deployment-TOML interface? - Backward-compatibility concerns? ## Additional context diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e199e65..b4fd8983 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -73,6 +73,11 @@ uv run mypy switchyard # Tests — no failures uv run pytest tests/ -v + +# Rust formatting, linting, and tests +cargo fmt --all --check +cargo clippy --workspace --all-targets -- -D warnings +cargo test --workspace ``` These commands run in CI on every push. **Fix linting errors locally before pushing:** @@ -130,6 +135,9 @@ feat(api)!: remove legacy route option uv run ruff check . uv run mypy switchyard uv run pytest tests/ -v + cargo fmt --all --check + cargo clippy --workspace --all-targets -- -D warnings + cargo test --workspace ``` 4. **Push and open a PR** on GitHub. Include: @@ -152,6 +160,7 @@ workflows (commitlint, PR title) run on every PR but are advisory. ```bash uv run pytest tests/ -v +cargo test --workspace ``` ### Integration tests (requires API keys) @@ -167,19 +176,38 @@ The default unit test suite runs with no network access and no API keys. Live, e ## Architecture -See [Agents](AGENTS.md) for the full architecture guide. Key points: - -- **Typed requests/responses** — use `ChatRequest` and `ChatResponse` subtypes -- **Composable chain** — `RequestProcessor` → `LLMBackend` → `ResponseProcessor` → `TranslationEngine` -- **Profiles** — pre-built chains in `switchyard/lib/profiles/` +See [Architecture](docs/architecture.md) for the request lifecycle and +[Agents](AGENTS.md) for crate boundaries and repository conventions. The +supported serving path is native Rust: -When adding a new component: +```text +HTTP request + → switchyard-server + → switchyard-translation (decode) + → libsy + → libsy-llm-client + → switchyard-translation (encode) + → upstream model +``` -1. Decide the role: `RequestProcessor`, `LLMBackend`, `ResponseProcessor`, or translation engine work. -2. Subclass the ABC from `switchyard/lib/roles.py`. -3. Put Python middleware in the matching subpackage (`switchyard/lib/processors/`, `switchyard/lib/backends/`) and provider translation logic in `crates/switchyard-translation`. -4. Add tests in `tests/`. -5. Export from the relevant `__init__.py` and from `switchyard/__init__.py`'s `__all__`. +Before making a change, identify the surface that owns it: + +- Put routing algorithms and driver behavior in `crates/libsy`. +- Put provider-neutral request and response types in `crates/protocol`. +- Put translated HTTP calls in `crates/libsy-llm-client`. +- Put wire-format conversion in `crates/switchyard-translation`. +- Put HTTP serving and deployment configuration in `crates/switchyard-server`. +- Put source-neutral skill-distillation records and port traits in + `crates/switchyard-skill-distillation`; that crate does not own workflow + orchestration. Test its public contracts in + `crates/switchyard-skill-distillation/tests/contracts.rs`. +- Put native Python bindings in `crates/switchyard-py`; keep Python wrappers in + `switchyard/libsy` or `switchyard_rust`. +- Put launcher behavior in `switchyard/cli`. + +Add Rust tests in the owning crate and Python tests in `tests/`. Export new +public symbols from the owning crate or package rather than the top-level +`switchyard` package unless that package owns the API. ## Documentation diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index e0826286..e9fae8ba 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -5,7 +5,7 @@ Switchyard itself. If you only want to **use** the package, see [README](README.md). For deeper architectural docs, see [Agents](AGENTS.md) and -[Architecture](docs/ARCHITECTURE.md). +[Architecture](docs/architecture.md). ## Setup @@ -40,30 +40,21 @@ uv sync --all-extras # everything (dev group is still included by default) ## Project Structure ``` -switchyard/ -├── switchyard/ # The package itself -│ ├── __init__.py # Public API exports (single source of truth) -│ ├── lib/ # Core library -│ │ ├── roles.py # RequestProcessor, LLMBackend, ResponseProcessor ABCs -│ │ ├── switchyard.py # Switchyard chain executor -│ │ ├── profiles/ # Profile configs/runtimes (passthrough, random_routing, …) -│ │ ├── proxy_context.py # ProxyContext — per-request state -│ │ ├── chat_request/ # Typed request hierarchy -│ │ ├── chat_response/ # Typed response hierarchy -│ │ ├── backends/ # LLMBackend implementations -│ │ ├── processors/ # RequestProcessor / ResponseProcessor implementations -│ │ ├── factories/ # MiddlewareFactory implementations + configs -│ │ └── endpoints/ # FastAPI endpoint wrappers (require [server]) -│ ├── cli/ # CLI entry point (requires [cli]) -│ └── server/ # FastAPI app factory + verify helpers (requires [server]) -├── crates/ -│ ├── switchyard-translation/ # Rust request/response/stream translation engine -│ └── switchyard-py/ # Thin PyO3 bindings plus Python convenience wrapper -├── tests/ # Pytest unit tests (no API keys required) -├── examples/ # Minimal usage examples -├── docs/ # Architecture, getting started, publication -├── secrets/ # Local credential template (git-ignored) -└── pyproject.toml +switchyard/ # Python package +├── cli/ # CLI and coding-agent launchers +└── libsy/ # Typed wrappers for libsy algorithms +switchyard_rust/ # Python facades over the PyO3 extension +crates/ +├── libsy/ # Routing algorithms and driver +├── libsy-llm-client/ # Translated HTTP model calls +├── protocol/ # Provider-neutral protocol types +├── switchyard-py/ # PyO3 bindings for libsy and the server +├── switchyard-server/ # Native HTTP server and TOML configuration +├── switchyard-skill-distillation/ # Skill-distillation contracts +└── switchyard-translation/ # Request, response, and stream translation +tests/ # Python tests (no API keys required) +docs/ # User and architecture documentation +pyproject.toml # Python package and development tooling ``` ## Development Workflow @@ -78,6 +69,11 @@ uv run pytest tests/ -v # Lint and type check uv run ruff check . uv run mypy switchyard + +# Rust formatting, linting, and tests +cargo fmt --all --check +cargo clippy --workspace --all-targets -- -D warnings +cargo test --workspace ``` > **Local Git hooks:** install both `pre-commit` and `commit-msg` hooks with