feat: support adding GitHub Copilot AI provider via UI (#25888)

Copilot is the only AI provider type that could not be added through the `/ai/settings` UI. The aibridge runtime and the env-var seeding path already supported it, but the runtime CRUD API rejected `type=copilot` and the UI omitted it entirely. The root cause is that Copilot's auth model (a per-request GitHub OAuth token, with no pre-shared key) does not fit the credential-centric add-provider flow that every other provider uses.

## Backend

Allow `type=copilot` in `CreateAIProviderRequest.Validate()`, and reject `api_keys` for Copilot on both create (validation) and update (handler sentinel), mirroring the existing Bedrock guards. Copilot carries no stored credential.

## Frontend

Add Copilot to the provider type picker (with the `github-copilot.svg` icon) and give the form a credential-free branch: name, display name, and a free-text endpoint defaulting to `https://api.business.githubcopilot.com`, with copy explaining that authentication happens via the user's GitHub token at request time. Copilot maps to the distinct `copilot` wire type rather than collapsing to `openai`, and the edit flow recovers it correctly.

The endpoint stays required with a business-tier default; users on the individual or enterprise endpoints edit the field.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
Danny Kopping
2026-06-01 15:26:37 +02:00
committed by GitHub
parent 82752844bc
commit a85462bd49
18 changed files with 457 additions and 36 deletions
+10 -2
View File
@@ -188,8 +188,9 @@ type AIProviderKey struct {
// CreateAIProviderRequest is the payload for creating a new AI
// provider. Name and Type are required. APIKeys carries the plaintext
// keys for OpenAI/Anthropic providers; Bedrock providers authenticate
// via Settings and must omit APIKeys.
// keys for OpenAI/Anthropic providers; Bedrock and Copilot providers
// must omit APIKeys (Bedrock authenticates via Settings, Copilot via
// request-time GitHub OAuth tokens).
type CreateAIProviderRequest struct {
Type AIProviderType `json:"type"`
Name string `json:"name"`
@@ -209,6 +210,7 @@ func (req CreateAIProviderRequest) Validate() []ValidationError {
AIProviderTypeAnthropic,
AIProviderTypeAzure,
AIProviderTypeBedrock,
AIProviderTypeCopilot,
AIProviderTypeGoogle,
AIProviderTypeOpenAICompat,
AIProviderTypeOpenrouter,
@@ -244,6 +246,12 @@ func (req CreateAIProviderRequest) Validate() []ValidationError {
Detail: "type=bedrock does not accept api_keys",
})
}
if req.Type == AIProviderTypeCopilot && len(req.APIKeys) > 0 {
validations = append(validations, ValidationError{
Field: "api_keys",
Detail: "type=copilot does not accept api_keys",
})
}
return validations
}