Thank you for your interest in contributing to cascadeflow! 🌊
We welcome contributions of all kinds: bug reports, documentation improvements, feature requests, and code contributions.
- Code of Conduct
- Monorepo Structure
- Getting Started
- Python Development
- TypeScript Development
- Making Changes
- Pull Request Process
- Reporting Bugs
- Suggesting Features
- Quick Reference
This project follows a Code of Conduct to ensure a welcoming environment for everyone. By participating, you agree to:
- Be respectful and considerate
- Welcome newcomers and help them get started
- Focus on constructive feedback
- Accept gracefully when your contribution is not accepted
cascadeflow is a monorepo containing both Python and TypeScript/JavaScript implementations:
cascadeflow/
├── cascadeflow/ # Python package
│ ├── core/ # Core cascade logic
│ ├── providers/ # Provider integrations
│ ├── quality/ # Quality validation
│ └── utils/ # Utilities & presets
├── packages/
│ ├── core/ # TypeScript/JavaScript core
│ │ └── src/ # TypeScript source
│ └── integrations/
│ └── n8n/ # n8n community node
├── docs/ # Documentation
├── examples/ # Python examples
└── tests/ # Python tests
Choose your track:
- 🐍 Python contributors: Work in
cascadeflow/directory - 📘 TypeScript contributors: Work in
packages/core/directory - 🔌 n8n contributors: Work in
packages/integrations/n8n/directory
For Python Development:
- Python 3.9 or higher
- Git
- Virtual environment tool (venv, virtualenv, or conda)
For TypeScript Development:
- Node.js 18 or higher
- pnpm (recommended) or npm
- Git
For Both:
- API keys for testing (OpenAI, Anthropic, Groq, etc.)
# Fork the repository on GitHub
# Clone your fork
git clone https://github.com/YOUR-USERNAME/cascadeflow.git
cd cascadeflow
# Add upstream remote
git remote add upstream https://github.com/lemony-ai/cascadeflow.gitpython -m venv .venv
source .venv/bin/activate # Linux/Mac
# or: .venv\Scripts\activate # Windows# Install in editable mode with dev dependencies
pip install -e ".[dev]"
# Or use requirements file
pip install -r requirements-dev.txtpre-commit installcp .env.example .env
# Add your API keys to .env# Run tests
pytest
# Check formatting
black --check cascadeflow/
ruff check cascadeflow/
# Run type checker
mypy cascadeflow/# Install pnpm if you don't have it
npm install -g pnpm
# Install all dependencies (from project root)
pnpm install# Build the core package
pnpm --filter @cascadeflow/core build
# Or build in watch mode for development
pnpm --filter @cascadeflow/core dev# Create .env file in packages/core/
cd packages/core
cp .env.example .env
# Add your API keys to .env# Run TypeScript compiler check
pnpm --filter @cascadeflow/core typecheck
# Run linter
pnpm --filter @cascadeflow/core lint
# Run tests
pnpm --filter @cascadeflow/core testTypeScript code is automatically formatted using ESLint and TypeScript.
# Lint and auto-fix
pnpm --filter @cascadeflow/core lint
# Type check
pnpm --filter @cascadeflow/core typecheck
# Format specific file
npx eslint src/yourfile.ts --fix- Indentation: 2 spaces
- Quotes: Single quotes for strings
- Semicolons: Required
- Line length: 100 characters
- Type annotations: Required for function parameters and return types
import { CascadeAgent, type ModelConfig } from './types';
/**
* Initialize a cascade agent with the given configuration
*
* @param models - Array of model configurations
* @returns Initialized cascade agent
*/
export function createAgent(models: ModelConfig[]): CascadeAgent {
if (models.length === 0) {
throw new Error('At least one model is required');
}
return new CascadeAgent({ models });
}# Run all tests
pnpm --filter @cascadeflow/core test
# Run tests in watch mode
pnpm --filter @cascadeflow/core test:watch
# Run specific test file
pnpm --filter @cascadeflow/core test src/agent.test.tsWe use Vitest for TypeScript testing:
import { describe, it, expect } from 'vitest';
import { CascadeAgent } from './agent';
describe('CascadeAgent', () => {
it('should initialize with models', () => {
const agent = new CascadeAgent({
models: [
{ name: 'gpt-4o-mini', provider: 'openai', cost: 0.00015 },
],
});
expect(agent).toBeDefined();
expect(agent.models).toHaveLength(1);
});
it('should run a query', async () => {
const agent = new CascadeAgent({
models: [
{ name: 'gpt-4o-mini', provider: 'openai', cost: 0.00015 },
],
});
const result = await agent.run('What is TypeScript?');
expect(result.content).toBeDefined();
expect(result.totalCost).toBeGreaterThan(0);
});
});# Build for production
pnpm --filter @cascadeflow/core build
# Build in development mode (with watch)
pnpm --filter @cascadeflow/core dev
# Clean build artifacts
pnpm --filter @cascadeflow/core cleanThe build creates multiple formats:
- CommonJS (
dist/index.js) - For Node.js - ESM (
dist/index.mjs) - For modern bundlers - Type Definitions (
dist/index.d.ts) - For TypeScript users
Before publishing:
- Update version in
package.json - Build the package:
pnpm build - Test the build:
pnpm test - Check types:
pnpm typecheck - Publish:
npm publish(maintainers only)
# Update your main branch
git checkout main
git pull upstream main
# Create a feature branch
git checkout -b feature/your-feature-name
# or
git checkout -b fix/bug-description- Write clear, concise code
- Add docstrings to functions and classes
- Update documentation if needed
- Add tests for new functionality
Follow conventional commit format:
git add .
git commit -m "type: description"Commit Types:
feat:- New featurefix:- Bug fixdocs:- Documentation changesstyle:- Code style changes (formatting, no logic change)refactor:- Code refactoringtest:- Adding or updating testschore:- Maintenance tasks
Examples:
git commit -m "feat: add support for custom quality thresholds"
git commit -m "fix: resolve token counting edge case"
git commit -m "docs: update installation guide"We use automated formatting tools to maintain consistent code style across the project.
Run the formatting script before every commit:
# Make script executable (first time only)
chmod +x scripts/format_code.sh
# Run formatting
./scripts/format_code.sh # macOS/Linux
# or
scripts\format_code.bat # WindowsThis script automatically runs:
- Black - Code formatter
- isort - Import sorter
- Ruff - Linter with auto-fix
- mypy - Type checker
If you prefer to run tools individually:
# Format code with Black
black cascadeflow/ tests/ examples/ --line-length 100
# Sort imports with isort
isort cascadeflow/ tests/ examples/ --profile black --line-length 100
# Fix linting issues with Ruff
ruff check cascadeflow/ tests/ examples/ --fix
# Check types with mypy
mypy cascadeflow/ --ignore-missing-imports| Tool | Purpose | Configuration |
|---|---|---|
| Black | Formats Python code to PEP 8 | Line length: 100 chars |
| isort | Sorts and organizes imports | Black-compatible profile |
| Ruff | Fast linter with auto-fix | Catches common issues |
| mypy | Static type checking | Validates type hints |
- Run
./scripts/format_code.sh(or.baton Windows) - Check
git diffto review formatting changes - Ensure all tests still pass:
pytest - Verify no new linting errors:
ruff check cascadeflow/
Our formatting follows these standards:
- Line length: 100 characters maximum
- Import order: stdlib → third-party → local (sorted alphabetically)
- Spacing: Consistent spacing around operators and after commas
- Quotes: Double quotes preferred by Black
- Type hints: Required for all public functions and methods
Before formatting:
from cascadeflow.quality import QualityValidator
import os
from typing import Optional,List
import asyncio
def process_query(query:str,model:str,temperature:float=0.7)->dict:
result=model.generate(query,temp=temperature)
return resultAfter formatting:
import asyncio
import os
from typing import List, Optional
from cascadeflow.quality import QualityValidator
def process_query(query: str, model: str, temperature: float = 0.7) -> dict:
result = model.generate(query, temp=temperature)
return resultOur CI pipeline automatically checks code formatting:
- Pull requests must pass all formatting checks
- Black, isort, Ruff, and mypy run on every PR
- Failed checks will block merging
Pro Tip: Set up pre-commit hooks to auto-format on commit:
pre-commit install# Run all tests
pytest
# Run specific test file
pytest tests/test_agent.py
# Run with coverage
pytest --cov=cascadeflow --cov-report=html
# Run with verbose output
pytest -v
# Run specific test
pytest tests/test_agent.py::test_smart_default- Add tests for all new features
- Test edge cases and error conditions
- Use descriptive test names
- Mock external API calls
Example:
import pytest
from cascadeflow import CascadeAgent, ModelConfig
def test_agent_initialization():
"""Test that agent initializes correctly."""
models = [
ModelConfig(name="gpt-4", provider="openai", cost=0.03)
]
agent = CascadeAgent(models=models)
assert agent is not None
assert len(agent.models) == 1
@pytest.mark.asyncio
async def test_agent_run():
"""Test agent.run() with mock provider."""
# Your test here
pass- All tests must pass before PR is merged
- Maintain or improve code coverage
- Include both unit and integration tests
We use automated tools to maintain consistent code style. Always run the formatting script before committing:
./scripts/format_code.sh # macOS/Linux
# or
scripts\format_code.bat # WindowsSee the Python Code Formatting section for details.
General:
- Line length: 100 characters
- Use type hints for function parameters and return values
- Write docstrings for all public functions and classes
Docstrings:
def example_function(param1: str, param2: int) -> bool:
"""
Short description of what the function does.
Args:
param1: Description of param1
param2: Description of param2
Returns:
Description of return value
Raises:
ValueError: When something goes wrong
"""
passNaming:
- Classes:
PascalCase - Functions/methods:
snake_case - Constants:
UPPER_SNAKE_CASE - Private methods:
_leading_underscore
-
Format your code
./scripts/format_code.sh # or format_code.bat on Windows -
Update your branch
git fetch upstream git rebase upstream/main
-
Run all checks
pytest black --check cascadeflow/ ruff check cascadeflow/ mypy cascadeflow/
-
Update documentation
- Update README.md if needed
- Update docstrings
- Add examples if applicable
-
Push your branch
git push origin feature/your-feature-name
-
Create Pull Request on GitHub
- Use a clear, descriptive title
- Reference related issues: "Fixes #123"
- Describe what changed and why
- Add screenshots if UI changes
-
PR Template
## Description Brief description of changes ## Type of Change - [ ] Bug fix - [ ] New feature - [ ] Documentation update - [ ] Performance improvement ## Testing - [ ] Tests pass locally - [ ] Added new tests - [ ] Updated documentation - [ ] Ran formatting script ## Related Issues Fixes #123
Branch Protection Rules:
- ✅ All PRs require approval from @saschabuehrle before merging
- ✅ Direct commits to
mainbranch are blocked (even for admins) - ✅ All changes must go through pull requests
- ✅ Code owners (defined in
.github/CODEOWNERS) are automatically requested for review - ✅ All conversations must be resolved before merging
- ✅ Linear history is enforced (no merge commits)
Review Steps:
- Maintainer will review your PR within 2-3 business days
- Address any requested changes promptly
- Push new commits to the same branch
- Maintainer will re-review and approve
- Once approved, maintainer will merge your PR
- Your contribution will be credited in release notes
Note: Even repository owners cannot bypass these rules - all changes must go through the PR process!
- Check existing issues for duplicates
- Try to reproduce with latest version
- Gather relevant information
Use the bug report template:
**Describe the bug**
Clear description of the bug
**To Reproduce**
Steps to reproduce:
1. Step one
2. Step two
3. See error
**Expected behavior**
What should happen
**Actual behavior**
What actually happens
**Environment**
- OS: Ubuntu 22.04
- Python: 3.11.5
- cascadeflow: 0.1.0
- Provider: OpenAI
**Additional context**
Any other relevant information- Check if feature already exists or is planned
- Check existing feature requests
- Consider if it fits project scope
**Feature Description**
What feature would you like to see?
**Use Case**
Why is this feature important?
What problem does it solve?
**Proposed Solution**
How should this work?
**Alternatives Considered**
What alternatives have you considered?
**Additional Context**
Any mockups, examples, or related features?- Create
cascadeflow/providers/your_provider.py - Inherit from
BaseProvider - Implement required methods
- Add to
PROVIDER_REGISTRY - Write tests in
tests/test_your_provider.py - Update documentation
- Format code:
./scripts/format_code.sh
- Discuss in an issue first (for major features)
- Write tests before implementation (TDD)
- Update relevant documentation
- Add examples if applicable
- Update CHANGELOG.md
- Format code before committing
- Profile code for performance-critical sections
- Avoid blocking operations in async code
- Cache expensive computations when possible
- Consider memory usage for large-scale deployments
# Setup
pip install -e ".[dev]"
# Format code (DO THIS BEFORE EVERY COMMIT!)
./scripts/format_code.sh # macOS/Linux
scripts\format_code.bat # Windows
# Test
pytest # Run all tests
pytest -v # Verbose output
pytest --cov=cascadeflow # With coverage
# Check code
black --check cascadeflow/ # Check formatting
ruff check cascadeflow/ # Check linting
mypy cascadeflow/ # Check types# Setup
pnpm install # Install dependencies
# Build
pnpm --filter @cascadeflow/core build # Production build
pnpm --filter @cascadeflow/core dev # Development build (watch)
# Test
pnpm --filter @cascadeflow/core test # Run all tests
pnpm --filter @cascadeflow/core test:watch # Watch mode
# Check code
pnpm --filter @cascadeflow/core lint # Lint and auto-fix
pnpm --filter @cascadeflow/core typecheck # Type check
# Clean
pnpm --filter @cascadeflow/core clean # Remove build artifactsgit checkout -b feature/name # Create branch
git add . # Stage changes
git commit -m "feat: message" # Commit with conventional format
git push origin feature/name # Push to your fork- Open an issue for questions
- Join our discussions
- Check existing documentation
Thank you for contributing to cascadeflow! 🚀