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:
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user