Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
8f6c468
feat: add GitHub Enterprise Server/Cloud support
jkorsvik Oct 13, 2025
32e948d
fix: use copilot-api subdomain for enterprise Copilot endpoints
jkorsvik Oct 13, 2025
6f07c56
chore: clean up docs and bump version to 0.8.0
jkorsvik Oct 13, 2025
ee4670a
refactor: clean up enterprise URL handling and simplify code patterns
jkorsvik Oct 13, 2025
151646e
feat: add AGENTS.md for build, lint, test commands and code style gui…
jkorsvik Oct 13, 2025
d9f3aad
Grafana
luisbrandao Oct 16, 2025
dc46615
Refactor code structure for improved readability and maintainability
luisbrandao Oct 28, 2025
265a2df
feat: include context size in token usage logs for chat completions
luisbrandao Oct 28, 2025
0f99cae
refactor: replace consola with console.log for token logging
luisbrandao Oct 28, 2025
1e6d259
feat: add tzdata installation for timezone support in Dockerfile
luisbrandao Oct 28, 2025
a7da48d
feat: add local timezone formatting for timestamps in chat completion…
luisbrandao Oct 28, 2025
29668ce
feat: support copilot reasoning_opaque and reasoning_text
caozhiyuan Nov 19, 2025
a2467d3
feat: add signature field to AnthropicThinkingBlock
caozhiyuan Nov 19, 2025
58f7a45
feat: add idleTimeout configuration for bun server
caozhiyuan Nov 19, 2025
3fa5519
feat: enhance reasoning handling in tool calls and change the thinkin…
caozhiyuan Nov 19, 2025
dfb40d2
feat: conditionally handle reasoningOpaque in handleFinish based on t…
caozhiyuan Nov 19, 2025
7657d87
fix: handleReasoningOpaqueInToolCalls add isToolBlockOpen judge
caozhiyuan Nov 20, 2025
968ff12
merge: integrate chat-completions-reasoning support
jkorsvik Nov 25, 2025
9b3f737
Merge branch 'feat/enterprise-and-reasoning'
luisbrandao Feb 19, 2026
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
Prev Previous commit
Next Next commit
fix: use copilot-api subdomain for enterprise Copilot endpoints
- Update copilotBaseUrl to use copilot-api.{enterprise} for GHE
- Add 6 new tests for copilotBaseUrl with enterprise configuration
- Update CLAUDE.md with correct enterprise endpoint documentation
- Fixes 'Failed to get models' error for GitHub Enterprise users

🤖 Generated with [Claude Code](https://claude.com/claude-code)
  • Loading branch information
jkorsvik committed Oct 13, 2025
commit 32e948d5f64132a8284b3208d6f3e61c8d41c77c
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Important notes for Claude Code instances
- Local dev: Use "bun run dev" to iterate with file watching; use "bun run start" for a production-like run.
- Authentication: The application persists GitHub tokens under ~/.local/share/copilot-api (see src/lib/paths.ts:5-12). Avoid exposing tokens in commits or logs.
- GitHub Enterprise support: Use --enterprise-url flags for GitHub Enterprise Server/Cloud. The CLI will prompt interactively during auth if no enterprise URL is provided. Enterprise host is persisted for subsequent runs.
- Enterprise URLs: Stored in APP_DIR/enterprise_url and normalized (scheme/slash stripped) before persistence. OAuth flows use https://{enterprise} endpoints, Copilot API uses https://api.{enterprise} endpoints.
- Enterprise URLs: Stored in APP_DIR/enterprise_url and normalized (scheme/slash stripped) before persistence. OAuth flows use https://{enterprise} endpoints, Copilot API uses https://copilot-api.{enterprise} for models and chat endpoints, and https://api.{enterprise} for token/usage endpoints.
- Rate limiting & manual approval: These behaviours are controlled in start.ts and state.ts; tests or changes touching rate limiting should check src/lib/rate-limit.ts.

Files and areas to inspect for common tasks
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,7 @@ bun run start
- `--wait`: Use this with `--rate-limit`. It makes the server wait for the cooldown period to end instead of rejecting the request with an error. This is useful for clients that don't automatically retry on rate limit errors.
- If you have a GitHub business or enterprise plan account with Copilot, use the `--account-type` flag (e.g., `--account-type business`). See the [official documentation](https://docs.github.com/en/enterprise-cloud@latest/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-access-to-github-copilot-in-your-organization/managing-github-copilot-access-to-your-organizations-network#configuring-copilot-subscription-based-network-routing-for-your-enterprise-or-organization) for more details.
- For GitHub Enterprise Server/Cloud users: Use `--enterprise-url` to specify your enterprise host (e.g., `--enterprise-url https://ghe.example.com`). The interactive auth command (`copilot-api auth`) will prompt you for your enterprise host if you don't provide it via the CLI flag.



export ANTHROPIC_BASE_URL=http://localhost:4141 ANTHROPIC_AUTH_TOKEN=dummy ANTHROPIC_MODEL=claude-sonnet-4.5 ANTHROPIC_DEFAULT_SONNET_MODEL=claude-sonnet-4.5 ANTHROPIC_SMALL_FAST_MODEL=gpt-5-mini ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5-mini DISABLE_NON_ESSENTIAL_MODEL_CALLS=1 CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 && claude
227 changes: 227 additions & 0 deletions TESTING_PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# Enterprise Support Testing Plan

## Overview
Comprehensive test plan to validate GitHub Enterprise Server/Cloud support in copilot-api.

## Test Categories

### 1. Unit Tests (Automated)
- [x] URL normalization helpers
- [x] githubBaseUrl with/without enterprise
- [x] githubApiBaseUrl with/without enterprise
- [x] looksLikeHost validation

### 2. Integration Tests (Manual + Automated)

#### 2.1 File System Persistence
**Test**: Enterprise URL persistence
- [ ] Write enterprise URL to file
- [ ] Read enterprise URL from file
- [ ] Verify file permissions (0600)
- [ ] Handle empty/missing file gracefully

**Test**: Token and enterprise URL coordination
- [ ] Token persisted alongside enterprise URL
- [ ] Both files created in APP_DIR
- [ ] Files survive process restart

#### 2.2 OAuth Flow with Enterprise
**Test**: Device code endpoint
- [ ] Mock fetch to verify URL: `https://{enterprise}/login/device/code`
- [ ] Verify client_id and scope in request body
- [ ] Handle response correctly

**Test**: Access token endpoint
- [ ] Mock fetch to verify URL: `https://{enterprise}/login/oauth/access_token`
- [ ] Verify device_code and grant_type in request body
- [ ] Poll correctly with enterprise URL

**Test**: Without enterprise (backwards compatibility)
- [ ] Device code uses `https://github.com/login/device/code`
- [ ] Access token uses `https://github.com/login/oauth/access_token`

#### 2.3 Copilot API with Enterprise
**Test**: Copilot token fetch
- [ ] Mock fetch to verify URL: `https://api.{enterprise}/copilot_internal/v2/token`
- [ ] Verify authorization header with GitHub token
- [ ] Handle token response

**Test**: Copilot usage fetch
- [ ] Mock fetch to verify URL: `https://api.{enterprise}/copilot_internal/user`
- [ ] Verify headers and response handling

**Test**: Get GitHub user
- [ ] Mock fetch to verify URL: `https://api.{enterprise}/user`
- [ ] Verify authorization header

**Test**: Token refresh
- [ ] Verify refresh interval uses enterprise URL
- [ ] State.enterpriseUrl persists across refresh

**Test**: Without enterprise (backwards compatibility)
- [ ] Copilot token uses `https://api.github.com/copilot_internal/v2/token`
- [ ] Usage uses `https://api.github.com/copilot_internal/user`

#### 2.4 CLI Argument Parsing
**Test**: auth command with --enterprise-url
- [ ] Parse flag correctly
- [ ] Pass to setupGitHubToken
- [ ] Persist to file

**Test**: auth command without flag (interactive)
- [ ] Prompt: "Are you using GitHub Enterprise?"
- [ ] If yes, prompt for host
- [ ] Normalize and persist host

**Test**: start command with --enterprise-url
- [ ] Parse flag correctly
- [ ] Override persisted value if present
- [ ] Set state.enterpriseUrl

**Test**: start command without flag
- [ ] Load persisted enterprise URL if present
- [ ] Use github.com if not present

#### 2.5 End-to-End Scenarios

**Scenario 1**: Fresh auth with enterprise (interactive)
```bash
bun run dev auth
# User prompted: "Are you using GitHub Enterprise?" -> y
# User prompted: "Enter host:" -> ghe.example.com
# Expected: Writes ghe.example.com to enterprise_url file
# Expected: Device code flow uses https://ghe.example.com/...
```

**Scenario 2**: Fresh auth with enterprise (CLI flag)
```bash
bun run dev auth --enterprise-url https://ghe.company.com/
# Expected: Normalizes to ghe.company.com
# Expected: Writes to enterprise_url file
# Expected: Device code flow uses https://ghe.company.com/...
```

**Scenario 3**: Start server with persisted enterprise
```bash
# Assume enterprise_url file contains "ghe.example.com"
bun run dev start
# Expected: Loads ghe.example.com from file
# Expected: All API calls use enterprise endpoints
```

**Scenario 4**: Start server with override
```bash
# Assume enterprise_url file contains "old.ghe.com"
bun run dev start --enterprise-url new.ghe.com
# Expected: Uses new.ghe.com for this run
# Expected: Does NOT overwrite persisted file (only auth writes)
```

**Scenario 5**: Backwards compatibility (no enterprise)
```bash
# No enterprise_url file present
bun run dev start
# Expected: All endpoints use github.com/api.github.com
```

**Scenario 6**: URL normalization variations
- Input: `https://ghe.example.com/` -> `ghe.example.com`
- Input: `http://ghe.example.com` -> `ghe.example.com`
- Input: `ghe.example.com` -> `ghe.example.com`
- Input: `ghe.example.com/` -> `ghe.example.com`

### 3. Mock-Based Integration Tests (to add)

Create `tests/enterprise-integration.test.ts`:

```typescript
import { describe, it, expect, mock, beforeEach, afterEach } from "bun:test"
import { setupGitHubToken } from "../src/lib/token"
import { state } from "../src/lib/state"

describe("Enterprise OAuth Flow", () => {
beforeEach(() => {
// Reset state
state.enterpriseUrl = undefined
})

it("should use enterprise URL for device code", async () => {
const fetchMock = mock((url: string) => {
expect(url).toBe("https://ghe.example.com/login/device/code")
return Promise.resolve({
ok: true,
json: () => Promise.resolve({
device_code: "test",
user_code: "ABCD-1234",
verification_uri: "https://ghe.example.com/login/device",
expires_in: 900,
interval: 5
})
})
})

global.fetch = fetchMock as any

state.enterpriseUrl = "ghe.example.com"
// Test device code fetch
// ...
})
})
```

## Test Execution Plan

### Phase 1: Automated Tests (Current)
- [x] Run existing unit tests: `bun test`
- [x] Verify all 38 tests pass

### Phase 2: Add Mock Integration Tests
- [ ] Create `tests/enterprise-integration.test.ts`
- [ ] Mock fetch for OAuth flows
- [ ] Mock fetch for Copilot API calls
- [ ] Verify correct URLs called
- [ ] Run: `bun test`

### Phase 3: Manual CLI Testing
- [ ] Test auth interactive flow
- [ ] Test auth with --enterprise-url flag
- [ ] Test start with persisted enterprise
- [ ] Test start with override
- [ ] Test backwards compatibility

### Phase 4: Real Enterprise Testing (if available)
- [ ] Test with actual GitHub Enterprise Server instance
- [ ] Complete full auth flow
- [ ] Verify Copilot token fetch
- [ ] Verify Copilot usage fetch
- [ ] Test server startup and API calls

## Test Results Log

### Automated Tests (Phase 1)
```
✅ bun test - 38 tests pass
✅ URL normalization tests pass
✅ Build succeeds
✅ Typecheck passes
```

### Integration Tests (Phase 2)
- Status: Pending

### Manual Tests (Phase 3)
- Status: Pending

### Real Enterprise Tests (Phase 4)
- Status: Pending (requires GHE instance)

## Known Limitations
- Cannot test against real GHE without access to instance
- Mock tests verify URL construction but not actual API compatibility
- Interactive prompt testing requires manual verification

## Next Steps
1. Create comprehensive mock-based integration tests
2. Add test for file system persistence
3. Manual CLI testing with mocked server responses
4. Document findings and any issues
Loading