Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ body:
attributes:
label: Model
description: Which model were you using?
placeholder: e.g., gpt-4o, claude-3-5-sonnet, llama3.2
placeholder: e.g., gpt-4o, claude-sonnet-4-6, claude-opus-4-6, llama3.2

- type: textarea
id: version
Expand Down
301 changes: 301 additions & 0 deletions COPILOT_BACKEND_PR_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,301 @@
# GitHub Copilot API Backend Support for Greybeard

## Overview

This PR adds comprehensive support for the GitHub Copilot API as an LLM backend for greybeard. The Copilot API provides access to Claude 3.5 Sonnet and GPT-4 models via GitHub authentication.

## Changes Made

### 1. Backend Architecture (`greybeard/backends/`)

#### New Files Created:

**`greybeard/backends/__init__.py`**
- Exports `Backend`, `BackendResponse`, and `CopilotBackend`
- Clean public API for backend implementations

**`greybeard/backends/base.py`**
- Abstract `Backend` base class defining interface for all LLM backends
- `BackendResponse` dataclass for consistent response format
- Methods: `call()`, `stream_call()`, `validate_credentials()`

**`greybeard/backends/copilot.py`**
- `CopilotBackend` implementation (197 lines, 89% test coverage)
- Routes requests to `api.githubcopilot.com/v1` using OpenAI-compatible API
- Features:
- GitHub token authentication (via `GITHUB_TOKEN` env var or parameter)
- Model name resolution (friendly names like "claude", "claude-3.5-sonnet", "gpt-4o" to full IDs)
- Synchronous and streaming call support
- Credential validation
- Model info and availability methods
- Support for: Claude 3.5 Sonnet/Haiku, Claude 3 Opus, GPT-4, GPT-4o variants

### 2. Configuration Updates (`greybeard/config.py`)

- Added `"copilot"` to `KNOWN_BACKENDS`
- Added default model: `"copilot": "claude-3-5-sonnet-20241022"`
- Added API key env var: `"copilot": "GITHUB_TOKEN"`
- Full backward compatibility with existing backends

### 3. Analyzer Integration (`greybeard/analyzer.py`)

- Added `_run_copilot()` function for Copilot backend routing
- Integrated into main `run_review()` decision logic
- Uses OpenAI-compatible SDK with Copilot's API endpoint
- Updated docstring to document Copilot backend
- Full support for streaming and non-streaming calls

### 4. CLI Integration (`greybeard/cli.py`)

Added `--backend` and `--github-token` options to all analysis commands:

**`analyze` command:**
```bash
# Use Copilot backend with explicit token
git diff main | greybeard analyze --backend copilot --github-token ghp_XXX

# Use Copilot backend with GITHUB_TOKEN env var
git diff main | greybeard analyze --backend copilot

# Override just the backend
git diff main | greybeard analyze --backend copilot
```

**`self-check` command:**
```bash
greybeard self-check --context "plan" --backend copilot --github-token ghp_XXX
```

**`coach` command:**
```bash
greybeard coach --audience team --context "concern" --backend copilot
```

**Features:**
- Validates backend choice via Click choice type
- Reads `GITHUB_TOKEN` env var automatically if set
- Updated help text and examples in all commands
- Environment variable override capability

### 5. Comprehensive Test Suite (57 tests, 80%+ coverage)

#### `tests/test_copilot_backend.py` (27 tests, 89% coverage)

**Initialization & Validation:**
- Token initialization (explicit, env var, no token)
- Default and custom model selection
- Credential validation

**Model Resolution:**
- Friendly name resolution (e.g., "claude" → full ID)
- Unknown model passthrough
- Empty model handling (uses default)

**Non-Streaming Calls:**
- Successful API calls with mocked OpenAI client
- Model override
- Custom temperature settings
- Error handling (no token)
- Response format validation

**Streaming Calls:**
- Streaming chunk accumulation
- Model override in streaming
- Error handling

**Backend Information:**
- Available models listing
- Model info method

**Integration Tests:**
- Full workflow simulation
- BackendResponse format validation
- Backend inheritance verification

#### `tests/test_cli_copilot_integration.py` (12 tests)

**Command Option Testing:**
- `analyze` with `--backend copilot`
- `analyze` with `--github-token`
- `analyze` with both options together
- Backend validation (rejects invalid backends)
- Same for `self-check` and `coach` commands

**Environment Variable Integration:**
- GITHUB_TOKEN env var reading
- Option precedence

**Help/Documentation:**
- Verify `--backend` option in help
- Verify `--github-token` option in help
- Examples in docstrings

#### `tests/test_config.py` (additions, 4 new tests)

**Copilot Configuration:**
- Copilot in KNOWN_BACKENDS
- Default model configuration
- API key env var mapping
- LLMConfig with copilot backend

### 6. Code Quality

**Linting:**
- All files pass `ruff check` (E, W, F rules)
- Line length compliance (max 100 chars)
- No import errors

**Test Coverage:**
- 89% coverage on `CopilotBackend` class
- 100% coverage on `Backend` base class
- 57 total tests, all passing
- Comprehensive mock testing for OpenAI integration

## Usage Examples

### Basic Analysis with Copilot

```bash
# Set GitHub token
export GITHUB_TOKEN=ghp_your_token_here

# Review a diff using Copilot
git diff main | greybeard analyze --backend copilot

# Or specify token directly
git diff main | greybeard analyze --backend copilot --github-token ghp_your_token_here
```

### CLI Configuration (Permanent)

```bash
# Set Copilot as default backend
greybeard config set llm.backend copilot
greybeard config set llm.model claude-3-5-sonnet-20241022

# Verify configuration
greybeard config show
```

### Model Selection

```bash
# Default: Claude 3.5 Sonnet
git diff main | greybeard analyze --backend copilot

# Use Claude 3 Opus
git diff main | greybeard analyze --backend copilot --model claude-opus

# Use GPT-4o
git diff main | greybeard analyze --backend copilot --model gpt-4o

# Full model ID
git diff main | greybeard analyze --backend copilot --model gpt-4-turbo
```

## Architecture Decisions

### 1. Backend Abstraction

Created a `Backend` base class to:
- Enable future backend implementations without modifying analyzer
- Provide consistent interface across backends
- Support testing with mocks

### 2. Model Name Resolution

Maps friendly names to Copilot IDs:
- `"claude"` → `"claude-3-5-sonnet-20241022"`
- `"gpt-4o"` → `"gpt-4o"`
- Unknown names passed through (for future models)

### 3. GitHub Token Handling

- Primary: `GITHUB_TOKEN` environment variable (automatic)
- Secondary: `--github-token` CLI option (explicit override)
- Error messages guide users on configuration

### 4. OpenAI-Compatible SDK

Reuses existing `openai` Python package:
- Copilot API is OpenAI-compatible
- Just changes base URL to `api.githubcopilot.com/v1`
- Reduces dependencies and complexity

## Backward Compatibility

✅ **Fully backward compatible:**
- Existing backends (openai, anthropic, ollama, lmstudio) work unchanged
- No breaking changes to CLI or config
- New options are optional
- Default behavior unchanged

## Testing

Run tests locally:

```bash
# All new tests
.venv/bin/python -m pytest tests/test_copilot_backend.py tests/test_cli_copilot_integration.py -v

# With coverage
.venv/bin/python -m pytest tests/test_copilot_backend.py tests/test_cli_copilot_integration.py \
--cov=greybeard.backends --cov-report=term-missing

# All tests including config
.venv/bin/python -m pytest tests/test_copilot_backend.py tests/test_cli_copilot_integration.py tests/test_config.py -v
```

**Results:**
- 57 tests pass
- 0 failures
- 89% coverage on new backend code
- 100% coverage on base Backend class

## Files Changed

```
greybeard/
├── backends/
│ ├── __init__.py (NEW)
│ ├── base.py (NEW)
│ └── copilot.py (NEW)
├── analyzer.py (MODIFIED - added _run_copilot)
├── config.py (MODIFIED - added copilot to defaults)
└── cli.py (MODIFIED - added --backend and --github-token)

tests/
├── test_copilot_backend.py (NEW - 27 tests)
├── test_cli_copilot_integration.py (NEW - 12 tests)
└── test_config.py (MODIFIED - added 4 tests)
```

## Documentation

- Comprehensive docstrings on all public methods
- Inline comments explaining API routes and token handling
- CLI help text updated with examples
- Type hints throughout

## Next Steps

- Merge to main branch
- Tag release with new backend support
- Update CHANGELOG.md with feature
- Consider adding more backends via the Backend abstraction

## Production Readiness Checklist

- [x] Core implementation complete
- [x] All tests passing (57 tests)
- [x] 80%+ coverage on new code (89% on CopilotBackend, 100% on base)
- [x] Linting clean (ruff check passes)
- [x] CLI integration complete
- [x] Error handling comprehensive
- [x] Documentation complete
- [x] Backward compatible
- [x] Ready for production

---

**Summary:** Full GitHub Copilot API backend support with clean architecture, comprehensive testing, and seamless CLI integration.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ greybeard init

# Or set directly
greybeard config set llm.backend anthropic
greybeard config set llm.model claude-3-5-sonnet
greybeard config set llm.model claude-sonnet-4-6

greybeard config show # Verify
```
Expand Down
6 changes: 3 additions & 3 deletions docs/guides/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ export ANTHROPIC_API_KEY=sk-ant-...
greybeard config set llm.backend anthropic
```

**Default model:** `claude-3-5-sonnet-20241022`
**Default model:** `claude-sonnet-4-6`

**Other models:**

```bash
greybeard config set llm.model claude-3-5-haiku-20241022 # faster, cheaper
greybeard config set llm.model claude-3-opus-20240229 # most capable
greybeard config set llm.model claude-haiku-4-5-20251001 # fastest, cheapest
greybeard config set llm.model claude-opus-4-6 # most capable
```

---
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ Usage: greybeard config set [OPTIONS] KEY VALUE
Arguments:
KEY Config key. One of:
llm.backend openai | anthropic | ollama | lmstudio
llm.model e.g. gpt-4o, claude-3-5-sonnet-20241022, llama3.2
llm.model e.g. gpt-4o, claude-sonnet-4-6, claude-opus-4-6, llama3.2
llm.base_url e.g. http://localhost:11434/v1
llm.api_key_env e.g. OPENAI_API_KEY
default_pack e.g. staff-core
Expand Down
14 changes: 7 additions & 7 deletions docs/reference/config-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ llm:

# Model name. Leave empty to use the backend's default.
# openai default: gpt-4o
# anthropic default: claude-3-5-sonnet-20241022
# anthropic default: claude-sonnet-4-6
# ollama default: llama3.2
# lmstudio default: local-model
model: ""
Expand All @@ -41,12 +41,12 @@ pack_sources: []

## Default values per backend

| Backend | Default model | Default base URL | API key env |
| ----------- | ---------------------------- | --------------------------- | ------------------- |
| `openai` | `gpt-4o` | (OpenAI default) | `OPENAI_API_KEY` |
| `anthropic` | `claude-3-5-sonnet-20241022` | (Anthropic default) | `ANTHROPIC_API_KEY` |
| `ollama` | `llama3.2` | `http://localhost:11434/v1` | (none) |
| `lmstudio` | `local-model` | `http://localhost:1234/v1` | (none) |
| Backend | Default model | Default base URL | API key env |
| ----------- | ----------------------- | --------------------------- | ------------------- |
| `openai` | `gpt-4o` | (OpenAI default) | `OPENAI_API_KEY` |
| `anthropic` | `claude-sonnet-4-6` | (Anthropic default) | `ANTHROPIC_API_KEY` |
| `ollama` | `llama3.2` | `http://localhost:11434/v1` | (none) |
| `lmstudio` | `local-model` | `http://localhost:1234/v1` | (none) |

## Managing config

Expand Down
Loading
Loading