Skip to main content

Development & Contribution

This guide covers how to contribute to Protolink, from setting up your development environment to submitting pull requests.

Getting Started​

Prerequisites​

[ Python ] [ Git ] [ uv ]
  • Python 3.11+ - Required for all development
  • Git - For version control
  • uv - Recommended package manager (or pip)

Clone and Setup​

# Clone the repository
git clone https://github.com/nMaroulis/protolink.git
cd protolink

# Install in development mode
uv pip install -e ".[dev]"
cd docs
npm install
cd ..

# Or with pip
pip install -e ".[dev]"
cd docs
npm install
cd ..

This installs Protolink in editable mode with all development dependencies.


Development Workflow​

1. Fork and Clone​

  1. Fork the repository on GitHub
  2. Clone your fork locally:
git clone https://github.com/<your-username>/protolink.git
cd protolink

# Add upstream for syncing
git remote add upstream https://github.com/nMaroulis/protolink.git

2. Create a Feature Branch​

git checkout -b feature/your-feature-name

3. Make Changes​

  • Write your code
  • Add tests for new functionality
  • Update documentation if needed

4. Quality Checks​

# Format code
ruff format .

# Lint and auto-fix
ruff check . --fix

# Type checking
ty check .

# Run tests
python -m pytest -v tests

# Benchmark prompt or infer-loop changes
python -m benchmarks.infer_loop --provider ollama --model <model> --suite smoke

# Validate docs
cd docs
npm run build
cd ..

5. Commit and Push​

git add .
git commit -m "feat: add your feature description"
git push origin feature/your-feature-name

6. Open Pull Request​

  • Open a PR from your fork to main
  • Describe your changes clearly
  • Include any breaking changes

Code Quality​

Formatting and Linting​

Protolink uses Ruff for code formatting and linting.

Ruff Configuration

The project uses the default Ruff configuration with some custom rules. See ruff.toml for details.

# Format all code
ruff format .

# Lint and auto-fix issues
ruff check . --fix

# Check without auto-fixing
ruff check .

Type Checking​

Protolink uses ty for static type checking.

The installed package includes a py.typed marker so type checkers can discover its inline annotations. Public tool decorators preserve the decorated function's callable type; keep overloads and return annotations aligned with runtime behavior when changing convenience APIs.

# Run type checks
ty check .

# Check one package area
ty check protolink/agents
Type Safety
  • All new code should be fully typed
  • Use str | None instead of Optional[str] (PEP 604)
  • Add type hints for all public APIs

Testing​

The optional live container check uses an existing Docker installation and a pre-pulled image containing /bin/sh, cat, id, ls, touch, grep and sleep. It verifies read-only mounts, network/capability restrictions, timeout and daemon cleanup without downloading images:

PROTOLINK_TEST_DOCKER_IMAGE=your-existing-test-image python -m pytest tests/test_container_backend.py

Without that environment variable, CLI fixture tests still verify argument construction, bounded output, cancellation and cleanup; the live daemon check is skipped. Use trusted images and disposable workspaces for integration tests.

Run the test suite with pytest:

# Run all tests
python -m pytest -v tests

# Run specific test file
python -m pytest -v tests/test_agent.py

# Run with coverage
python -m pytest --cov=protolink tests
Test Structure
  • Unit tests: tests/test_*.py
  • Integration tests: tests/integration/
  • Fixtures and utilities in tests/conftest.py

Development Tools​

Pre-commit Hooks​

The project includes pre-commit hooks for code quality:

# Install pre-commit hooks
pre-commit install

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

Documentation​

Preview documentation locally:

cd docs

# Serve docs
npm run start

# Validate docs
npm run build

# Open http://localhost:3000/protolink/

Deploy documentation (maintainers only):

cd docs
npm run build

Pull requests run npm run build from docs/. Pushes to main that touch docs, the README, Docusaurus configuration, or docs dependencies upload docs/build as a GitHub Pages artifact and deploy it through the github-pages environment.

The site uses EasyOps local search. npm run build indexes the rendered documentation, including section headings and API content, and ships the index with the static site. Search runs in the browser and requires no search-service credentials or separate indexing deployment. The index filename includes a content hash so updates invalidate cached indexes.

To check search locally, serve the production build:

cd docs
npm ci
npm run build
npm run serve

Open http://localhost:3000/protolink/ and use the navbar search field or Ctrl+K / Cmd+K. Check both dotted API identifiers and constructor parameter names, then follow a result to confirm its section anchor. Search indexes are generated by the production build, so use npm run serve when validating results rather than relying on npm run start. Search options live in docs/docusaurus.config.js; docsDir: "content" and docsRouteBasePath: "docs" match the documentation source and published route.


Project Structure​

protolink/
├── protolink/ # Main package
│ ├── agents/ # Agent implementations
│ ├── client/ # Client code
│ ├── core/ # Core models
│ ├── discovery/ # Registry and discovery
│ ├── llms/ # LLM integrations, infer loop, parsing and metrics
│ ├── models/ # Exposes core models for importation
│ ├── server/ # Server implementations
│ ├── transport/ # Transport layers
│ ├── tools/ # Tools and adapters (e.g. MCP)
│ ├── types/ # Type aliases
│ └── utils/ # Utilities
├── tests/ # Test suite
├── benchmarks/ # Repository-only regression and performance benchmarks
├── docs/ # Documentation
├── examples/ # Example scripts
└── README.md # Project overview

Infer-loop Benchmark​

Prompt, parsing, action-selection, retry and delegation changes should be checked with the repository-local infer-loop benchmark. It reports strict and functional correctness, failures and traces, task and model-call latency, Ollama prompt/load/generation timing and cache-sensitive repeat comparisons.

Run it from the repository root:

python -m benchmarks.infer_loop \
--provider ollama \
--model <model> \
--suite core \
--repetitions 2

Keep the provider, exact model and parameters, suite, seed, warm-up, attempts, repetitions, hardware and host load controlled in before-and-after runs. See the Infer-loop Benchmark guide for scoring, timing, baseline comparison and artifacts.


Contribution Guidelines​

Code Style​

  • Follow PEP 8 and PEP 604
  • Use descriptive variable and function names
  • Add docstrings for all public functions and classes
  • Keep functions focused and single-purpose

Commit Messages​

Use conventional commits:

  • feat: - New features
  • fix: - Bug fixes
  • docs: - Documentation changes
  • style: - Code style changes
  • refactor: - Code refactoring
  • test: - Test changes
  • chore: - Maintenance tasks

Pull Request Process​

  1. Update Documentation - If your change affects user-facing APIs
  2. Add Tests - Ensure new functionality is covered
  3. Pass CI - All checks must pass
  4. Review - Address feedback from maintainers
Breaking Changes

If your change includes breaking changes:

  • Clearly document them in the PR
  • Update every version source listed in the Release Process
  • Add migration notes to documentation

Debugging and Troubleshooting​

Common Issues​

Type Checking Errors​

# Check specific file for detailed errors
ty check protolink/your/file.py --verbose

Test Failures​

# Run tests with detailed output
pytest -v -s tests/test_failing.py

# Run specific test with debugging
pytest -v -s tests/test_failing.py::test_function

Import Issues​

# Install in development mode
python -m pip install -e .

# Check Python path
python -c "import protolink; print(protolink.__file__)"

Development Tips​

  • Use uv for faster dependency management
  • Enable debug logging: export PROTOLINK_LOG_LEVEL=debug
  • Use breakpoints: import pdb; pdb.set_trace()
  • For watch-mode testing, install a watcher such as pytest-watch locally and run it outside the core dependency set.

Release Process​

Maintainers can follow this process for releases:

  1. Update Python version sources in pyproject.toml and protolink/__version__.py, then regenerate uv.lock.
  2. Update documentation package metadata in docs/package.json and regenerate docs/package-lock.json. Keep guides and API references focused on current behavior; record ProtoLink release numbers and feature history in the changelog. Retain version numbers where they identify actual dependency requirements or protocol contracts.
  3. Finalize the changelog in docs/content/changelog.md: replace Unreleased with the publication date and move the latest-release note to the new version.
  4. Run release gates: formatting, linting, type checking, the full test suite, the Docusaurus production build, python -m build and python -m twine check dist/*. Check that the wheel and source distribution include protolink/py.typed, that installed metadata and protolink.__version__ agree and that the first getting-started example runs using only the base dependencies.
  5. Tag Release: git tag vX.Y.Z
  6. Push Tags: git push origin --tags
  7. Upload to PyPI: python -m twine upload dist/*

Community​

Getting Help​

  • GitHub Issues - Bug reports and feature requests
  • Discussions - General questions and ideas
  • Documentation - API reference and guides

Code of Conduct​

Please be respectful and constructive in all interactions. By participating in this project, you agree to follow our community guidelines.


Thank you for contributing to Protolink.