Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- Backward-compatibility concerns?

## Additional context
Expand Down
50 changes: 39 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:**
Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand All @@ -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
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

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

Expand Down
46 changes: 21 additions & 25 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading