feat(auth): add OAuth2 support for xAI with PKCE and token persistence

- Implemented xAI OAuth2 integration with PKCE (Proof Key for Code Exchange) support.
- Added logic for token exchange, refresh, and persistent storage in JSON format.
- Created `xai` package with helpers for OAuth discovery, API token handling, and URL building.
- Introduced `XAIExecutor` for integrating xAI credentials into runtime HTTP requests.
- Added unit tests to validate OAuth flow, token persistence, and endpoint validation.
This commit is contained in:
Luis Pater
2026-05-17 01:02:35 +08:00
parent cd0cea393c
commit e4c957078c
24 changed files with 2050 additions and 4 deletions
+10
View File
@@ -21,6 +21,7 @@ type staticModelsJSON struct {
CodexPro []*ModelInfo `json:"codex-pro"`
Kimi []*ModelInfo `json:"kimi"`
Antigravity []*ModelInfo `json:"antigravity"`
XAI []*ModelInfo `json:"xai"`
}
// GetClaudeModels returns the standard Claude model definitions.
@@ -78,6 +79,11 @@ func GetAntigravityModels() []*ModelInfo {
return cloneModelInfos(getModels().Antigravity)
}
// GetXAIModels returns the standard xAI Grok model definitions.
func GetXAIModels() []*ModelInfo {
return cloneModelInfos(getModels().XAI)
}
// WithCodexBuiltins injects hard-coded Codex-only model definitions that should
// not depend on remote models.json updates. Built-ins replace any matching IDs
// already present in the provided slice.
@@ -167,6 +173,7 @@ func cloneModelInfos(models []*ModelInfo) []*ModelInfo {
// - codex
// - kimi
// - antigravity
// - xai
func GetStaticModelDefinitionsByChannel(channel string) []*ModelInfo {
key := strings.ToLower(strings.TrimSpace(channel))
switch key {
@@ -186,6 +193,8 @@ func GetStaticModelDefinitionsByChannel(channel string) []*ModelInfo {
return GetKimiModels()
case "antigravity":
return GetAntigravityModels()
case "xai", "x-ai", "grok":
return GetXAIModels()
default:
return nil
}
@@ -208,6 +217,7 @@ func LookupStaticModelInfo(modelID string) *ModelInfo {
data.CodexPro,
data.Kimi,
data.Antigravity,
data.XAI,
}
for _, models := range allModels {
for _, m := range models {
+2
View File
@@ -215,6 +215,7 @@ func detectChangedProviders(oldData, newData *staticModelsJSON) []string {
{"codex", oldData.CodexPro, newData.CodexPro},
{"kimi", oldData.Kimi, newData.Kimi},
{"antigravity", oldData.Antigravity, newData.Antigravity},
{"xai", oldData.XAI, newData.XAI},
}
seen := make(map[string]bool, len(sections))
@@ -335,6 +336,7 @@ func validateModelsCatalog(data *staticModelsJSON) error {
{name: "codex-pro", models: data.CodexPro},
{name: "kimi", models: data.Kimi},
{name: "antigravity", models: data.Antigravity},
{name: "xai", models: data.XAI},
}
for _, section := range requiredSections {
+106 -1
View File
@@ -46,7 +46,8 @@
"levels": [
"low",
"medium",
"high"
"high",
"xhigh"
]
}
},
@@ -2064,5 +2065,109 @@
]
}
}
],
"xai": [
{
"id": "grok-4.3",
"object": "model",
"created": 1775606400,
"owned_by": "xai",
"type": "xai",
"display_name": "Grok 4.3",
"name": "grok-4.3",
"description": "xAI Grok 4.3 model for the Responses API.",
"context_length": 1000000,
"max_completion_tokens": 65536,
"thinking": {
"zero_allowed": true,
"levels": [
"none",
"low",
"medium",
"high"
]
}
},
{
"id": "grok-4.20-0309-reasoning",
"object": "model",
"created": 1773014400,
"owned_by": "xai",
"type": "xai",
"display_name": "Grok 4.20 0309 Reasoning",
"name": "grok-4.20-0309-reasoning",
"description": "xAI Grok 4.20 0309 reasoning model for the Responses API.",
"context_length": 2000000,
"max_completion_tokens": 65536
},
{
"id": "grok-4.20-0309-non-reasoning",
"object": "model",
"created": 1773014400,
"owned_by": "xai",
"type": "xai",
"display_name": "Grok 4.20 0309 Non Reasoning",
"name": "grok-4.20-0309-non-reasoning",
"description": "xAI Grok 4.20 0309 non-reasoning model for the Responses API.",
"context_length": 2000000,
"max_completion_tokens": 65536
},
{
"id": "grok-4.20-multi-agent-0309",
"object": "model",
"created": 1773014400,
"owned_by": "xai",
"type": "xai",
"display_name": "Grok 4.20 Multi Agent 0309",
"name": "grok-4.20-multi-agent-0309",
"description": "xAI Grok 4.20 multi-agent model for the Responses API.",
"context_length": 2000000,
"max_completion_tokens": 65536,
"thinking": {
"levels": [
"low",
"medium",
"high"
]
}
},
{
"id": "grok-3-mini",
"object": "model",
"created": 1740960000,
"owned_by": "xai",
"type": "xai",
"display_name": "Grok 3 Mini",
"name": "grok-3-mini",
"description": "xAI Grok 3 Mini model for the Responses API.",
"context_length": 131072,
"max_completion_tokens": 32768,
"thinking": {
"levels": [
"low",
"medium",
"high"
]
}
},
{
"id": "grok-3-mini-fast",
"object": "model",
"created": 1740960000,
"owned_by": "xai",
"type": "xai",
"display_name": "Grok 3 Mini Fast",
"name": "grok-3-mini-fast",
"description": "xAI Grok 3 Mini Fast model for the Responses API.",
"context_length": 131072,
"max_completion_tokens": 32768,
"thinking": {
"levels": [
"low",
"medium",
"high"
]
}
}
]
}