Skip to content

Latest commit

 

History

History
314 lines (222 loc) · 7.17 KB

File metadata and controls

314 lines (222 loc) · 7.17 KB

Contributing to Bond

Thank you for your interest in contributing to Bond! This document provides guidelines and instructions for contributing.

Table of Contents

Code of Conduct

Please be respectful and constructive in all interactions. We welcome contributors of all backgrounds and experience levels.

Getting Started

Reporting Bugs

Before reporting a bug:

  1. Search existing issues to avoid duplicates
  2. If none exists, open a new issue with:
    • A clear, descriptive title
    • Steps to reproduce the issue
    • Expected vs actual behavior
    • Python version and OS
    • Relevant error messages or stack traces

Suggesting Features

Feature requests are welcome! Please:

  1. Check existing issues for similar requests
  2. Open a new issue describing:
    • The use case or problem you're solving
    • Your proposed solution
    • Any alternatives you've considered

First-Time Contributors

Look for issues labeled good first issue for beginner-friendly tasks.

Development Setup

Prerequisites

Setup Steps

# 1. Fork the repository on GitHub

# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/bond-agent.git
cd bond-agent

# 3. Add upstream remote
git remote add upstream https://github.com/renbytes/bond-agent.git

# 4. Install dependencies
uv sync --group dev

# 5. Install pre-commit hooks
uv run pre-commit install

# 6. Verify setup
uv run pytest

Making Changes

Branch Naming

Create a branch from main with a descriptive name:

git checkout main
git pull upstream main
git checkout -b type/short-description

Branch types:

  • feat/ - New features
  • fix/ - Bug fixes
  • docs/ - Documentation only
  • refactor/ - Code refactoring
  • test/ - Test additions or fixes

Commit Messages

Write clear, concise commit messages:

type: short description

Longer explanation if needed. Wrap at 72 characters.

- Bullet points are fine
- Explain what and why, not how

Types: feat, fix, docs, refactor, test, chore

Examples:

  • feat: add GitHub repository search tool
  • fix: handle rate limit errors in GitHub adapter
  • docs: add streaming server guide

Pull Request Process

  1. Update your branch with the latest upstream changes:

    git fetch upstream
    git rebase upstream/main
  2. Run all checks before pushing:

    uv run pre-commit run --all-files
    uv run pytest
  3. Push your branch and open a PR:

    git push origin your-branch-name
  4. Fill out the PR template with:

    • Summary of changes
    • Link to related issues
    • Test plan
  5. Address review feedback promptly

PR Requirements

  • All CI checks must pass
  • Code must be formatted and linted
  • New features require tests
  • Documentation updates for user-facing changes

Code Style

Formatting and Linting

Bond uses Ruff for formatting and linting:

# Format code
uv run ruff format src tests

# Lint and auto-fix
uv run ruff check --fix src tests

Type Checking

Bond uses strict mypy type checking:

uv run mypy src/bond

All new code must be fully typed. Key rules:

  • No Any types without justification
  • All function parameters and returns typed
  • Use Protocol for duck typing

Pre-commit Hooks

Pre-commit runs automatically on each commit:

# Run manually
uv run pre-commit run --all-files

Hooks:

  1. ruff format - Auto-formats code
  2. ruff check --fix - Lints and auto-fixes
  3. mypy - Type checks

Testing

Running Tests

# Run all tests with coverage
uv run pytest

# Run specific test file
uv run pytest tests/unit/tools/github/test_adapter.py

# Run tests matching a pattern
uv run pytest -k "github"

# Run with verbose output
uv run pytest -v

Writing Tests

  • Place tests in tests/ mirroring the src/ structure
  • Use pytest fixtures for setup
  • Use respx for mocking HTTP requests
  • Aim for high coverage on new code

Example test:

import pytest
from bond.tools.github import GitHubAdapter

@pytest.fixture
def adapter():
    return GitHubAdapter(token="test-token")

async def test_get_repo_returns_info(adapter, respx_mock):
    respx_mock.get("https://api.github.com/repos/owner/repo").respond(
        json={"name": "repo", "description": "A test repo"}
    )

    result = await adapter.get_repo("owner", "repo")

    assert result.name == "repo"
    assert result.description == "A test repo"

Documentation

Building Docs

# Install docs dependencies
uv sync --extra docs

# Serve locally with hot reload
uv run mkdocs serve

# Build and check for errors
uv run mkdocs build --strict

Documentation Guidelines

  • Update docs for user-facing changes
  • Use Google-style docstrings
  • Include code examples
  • Keep API reference in docs/api/ in sync

Docstring Example

def get_repo(self, owner: str, repo: str) -> RepoInfo:
    """Get repository metadata.

    Args:
        owner: Repository owner (user or organization).
        repo: Repository name.

    Returns:
        Repository information including description, stars, and topics.

    Raises:
        RepoNotFoundError: If the repository doesn't exist.
        RateLimitedError: If API rate limit is exceeded.
    """

Project Structure

src/bond/
├── __init__.py          # Package exports
├── agent.py             # BondAgent implementation
├── utils.py             # StreamHandlers utilities
├── server/              # HTTP server module
├── tools/               # Bundled toolsets
│   ├── github/          # GitHub API tools
│   ├── githunter/       # Git forensics tools
│   ├── memory/          # Semantic memory tools
│   └── schema/          # Schema extraction tools
└── trace/               # Execution tracing

Adding a New Toolset

See Adding Tools for the complete guide.

Each toolset follows this structure:

tools/my_tool/
├── __init__.py          # Public API exports
├── _protocols.py        # Protocol definition
├── _types.py            # Pydantic models
├── _adapter.py          # Protocol implementation
└── tools.py             # Tool functions

Questions?

Thank you for contributing!