mirror of
https://gh-proxy.org/https://github.com/klinsmaya/CLIProxyAPI.git
synced 2026-11-09 09:56:49 +08:00
feat(models): add support for grok-imagine-video-1.5-preview model
- Introduced `grok-imagine-video-1.5-preview` as a new XAI video model. - Updated handlers, registry, and validation logic to include support for the new model. - Enhanced test coverage to validate integration and functionality of the preview model.
This commit is contained in:
@@ -269,6 +269,7 @@ func TestModelsWithClientVersionReturnsCodexCatalog(t *testing.T) {
|
||||
{ID: "gpt-image-2", Object: "model", OwnedBy: "openai", Type: "openai"},
|
||||
{ID: "grok-imagine-image", Object: "model", OwnedBy: "xai", Type: "openai"},
|
||||
{ID: "grok-imagine-video", Object: "model", OwnedBy: "xai", Type: "openai"},
|
||||
{ID: "grok-imagine-video-1.5-preview", Object: "model", OwnedBy: "xai", Type: "openai"},
|
||||
})
|
||||
t.Cleanup(func() {
|
||||
modelRegistry.UnregisterClient(clientID)
|
||||
@@ -355,10 +356,11 @@ func TestModelsWithClientVersionReturnsCodexCatalog(t *testing.T) {
|
||||
}
|
||||
|
||||
hiddenModels := map[string]bool{
|
||||
"grok-imagine-image-quality": false,
|
||||
"gpt-image-2": false,
|
||||
"grok-imagine-image": false,
|
||||
"grok-imagine-video": false,
|
||||
"grok-imagine-image-quality": false,
|
||||
"gpt-image-2": false,
|
||||
"grok-imagine-image": false,
|
||||
"grok-imagine-video": false,
|
||||
"grok-imagine-video-1.5-preview": false,
|
||||
}
|
||||
for _, model := range resp.Models {
|
||||
slug, _ := model["slug"].(string)
|
||||
|
||||
@@ -7,10 +7,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
codexBuiltinImageModelID = "gpt-image-2"
|
||||
xaiBuiltinImageModelID = "grok-imagine-image"
|
||||
xaiBuiltinImageQualityModelID = "grok-imagine-image-quality"
|
||||
xaiBuiltinVideoModelID = "grok-imagine-video"
|
||||
codexBuiltinImageModelID = "gpt-image-2"
|
||||
xaiBuiltinImageModelID = "grok-imagine-image"
|
||||
xaiBuiltinImageQualityModelID = "grok-imagine-image-quality"
|
||||
xaiBuiltinVideoModelID = "grok-imagine-video"
|
||||
xaiBuiltinVideo15PreviewModelID = "grok-imagine-video-1.5-preview"
|
||||
)
|
||||
|
||||
// staticModelsJSON mirrors the top-level structure of models.json.
|
||||
@@ -99,7 +100,7 @@ func WithCodexBuiltins(models []*ModelInfo) []*ModelInfo {
|
||||
// WithXAIBuiltins injects hard-coded xAI image/video model definitions that should
|
||||
// not depend on remote models.json updates.
|
||||
func WithXAIBuiltins(models []*ModelInfo) []*ModelInfo {
|
||||
return upsertModelInfos(models, xaiBuiltinImageModelInfo(), xaiBuiltinImageQualityModelInfo(), xaiBuiltinVideoModelInfo())
|
||||
return upsertModelInfos(models, xaiBuiltinImageModelInfo(), xaiBuiltinImageQualityModelInfo(), xaiBuiltinVideoModelInfo(), xaiBuiltinVideo15PreviewModelInfo())
|
||||
}
|
||||
|
||||
func codexBuiltinImageModelInfo() *ModelInfo {
|
||||
@@ -153,6 +154,19 @@ func xaiBuiltinVideoModelInfo() *ModelInfo {
|
||||
}
|
||||
}
|
||||
|
||||
func xaiBuiltinVideo15PreviewModelInfo() *ModelInfo {
|
||||
return &ModelInfo{
|
||||
ID: xaiBuiltinVideo15PreviewModelID,
|
||||
Object: "model",
|
||||
Created: 1735689600, // 2025-01-01
|
||||
OwnedBy: "xai",
|
||||
Type: "xai",
|
||||
DisplayName: "Grok Imagine Video 1.5 Preview",
|
||||
Name: xaiBuiltinVideo15PreviewModelID,
|
||||
Description: "xAI Grok preview video generation model.",
|
||||
}
|
||||
}
|
||||
|
||||
func upsertModelInfos(models []*ModelInfo, extras ...*ModelInfo) []*ModelInfo {
|
||||
if len(extras) == 0 {
|
||||
return models
|
||||
|
||||
@@ -151,7 +151,7 @@ func applyCodexClientModelMetadata(entry map[string]any, id string, model map[st
|
||||
|
||||
func applyCodexClientVisibilityOverride(entry map[string]any, id string) {
|
||||
switch strings.TrimSpace(id) {
|
||||
case "grok-imagine-image-quality", "gpt-image-2", "grok-imagine-image", "grok-imagine-video":
|
||||
case "grok-imagine-image-quality", "gpt-image-2", "grok-imagine-image", "grok-imagine-video", "grok-imagine-video-1.5-preview":
|
||||
entry["visibility"] = "hide"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ const (
|
||||
xaiVideosEditsAPI = "/v1/videos/edits"
|
||||
xaiVideosExtensionsAPI = "/v1/videos/extensions"
|
||||
defaultXAIVideosModel = "grok-imagine-video"
|
||||
xaiVideos15PreviewModel = "grok-imagine-video-1.5-preview"
|
||||
xaiVideosHandlerType = "openai-video"
|
||||
defaultVideosSeconds = "4"
|
||||
defaultVideosSize = "720x1280"
|
||||
@@ -45,7 +46,7 @@ func videosModelBase(model string) string {
|
||||
func isXAIVideosModel(model string) bool {
|
||||
prefix, baseModel := imagesModelParts(model)
|
||||
baseModel = strings.ToLower(strings.TrimSpace(baseModel))
|
||||
if baseModel != defaultXAIVideosModel {
|
||||
if baseModel != defaultXAIVideosModel && baseModel != xaiVideos15PreviewModel {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -86,8 +87,11 @@ func rejectUnsupportedNativeVideosModel(c *gin.Context, model string) bool {
|
||||
}
|
||||
|
||||
func canonicalXAIVideosModel(model string) string {
|
||||
if videosModelBase(model) == defaultXAIVideosModel {
|
||||
switch videosModelBase(model) {
|
||||
case defaultXAIVideosModel:
|
||||
return defaultXAIVideosModel
|
||||
case xaiVideos15PreviewModel:
|
||||
return xaiVideos15PreviewModel
|
||||
}
|
||||
return defaultXAIVideosModel
|
||||
}
|
||||
@@ -190,8 +194,9 @@ func buildXAIVideosCreateRequest(rawJSON []byte, model string) ([]byte, xaiVideo
|
||||
seconds = "10"
|
||||
}
|
||||
|
||||
videoModel := canonicalXAIVideosModel(model)
|
||||
req := []byte(`{}`)
|
||||
req, _ = sjson.SetBytes(req, "model", canonicalXAIVideosModel(model))
|
||||
req, _ = sjson.SetBytes(req, "model", videoModel)
|
||||
req, _ = sjson.SetBytes(req, "prompt", prompt)
|
||||
req, _ = sjson.SetRawBytes(req, "duration", []byte(strconv.FormatInt(duration, 10)))
|
||||
req, _ = sjson.SetBytes(req, "aspect_ratio", aspectRatio)
|
||||
@@ -204,7 +209,7 @@ func buildXAIVideosCreateRequest(rawJSON []byte, model string) ([]byte, xaiVideo
|
||||
}
|
||||
|
||||
meta := xaiVideoCreateMetadata{
|
||||
Model: defaultXAIVideosModel,
|
||||
Model: videoModel,
|
||||
Prompt: prompt,
|
||||
Seconds: seconds,
|
||||
Size: size,
|
||||
|
||||
@@ -33,7 +33,16 @@ func performVideosEndpointRequest(t *testing.T, method string, endpointPath stri
|
||||
}
|
||||
|
||||
func TestVideosModelValidationAllowsXAIVideoModel(t *testing.T) {
|
||||
for _, model := range []string{"grok-imagine-video", "xai/grok-imagine-video", "x-ai/grok-imagine-video", "grok/grok-imagine-video"} {
|
||||
for _, model := range []string{
|
||||
"grok-imagine-video",
|
||||
"xai/grok-imagine-video",
|
||||
"x-ai/grok-imagine-video",
|
||||
"grok/grok-imagine-video",
|
||||
"grok-imagine-video-1.5-preview",
|
||||
"xai/grok-imagine-video-1.5-preview",
|
||||
"x-ai/grok-imagine-video-1.5-preview",
|
||||
"grok/grok-imagine-video-1.5-preview",
|
||||
} {
|
||||
if !isSupportedVideosModel(model) {
|
||||
t.Fatalf("expected %s to be supported", model)
|
||||
}
|
||||
@@ -44,6 +53,9 @@ func TestVideosModelValidationAllowsXAIVideoModel(t *testing.T) {
|
||||
if isSupportedVideosModel("codex/grok-imagine-video") {
|
||||
t.Fatal("expected codex/grok-imagine-video to be rejected")
|
||||
}
|
||||
if isSupportedVideosModel("codex/grok-imagine-video-1.5-preview") {
|
||||
t.Fatal("expected codex/grok-imagine-video-1.5-preview to be rejected")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildXAIVideosCreateRequest(t *testing.T) {
|
||||
@@ -77,6 +89,22 @@ func TestBuildXAIVideosCreateRequest(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildXAIVideosCreateRequestAllowsPreviewModel(t *testing.T) {
|
||||
rawJSON := []byte(`{"model":"xai/grok-imagine-video-1.5-preview","prompt":"a cat playing piano","seconds":"8"}`)
|
||||
|
||||
req, meta, err := buildXAIVideosCreateRequest(rawJSON, "xai/grok-imagine-video-1.5-preview")
|
||||
if err != nil {
|
||||
t.Fatalf("buildXAIVideosCreateRequest() error = %v", err)
|
||||
}
|
||||
|
||||
if got := gjson.GetBytes(req, "model").String(); got != xaiVideos15PreviewModel {
|
||||
t.Fatalf("model = %q, want %s", got, xaiVideos15PreviewModel)
|
||||
}
|
||||
if meta.Model != xaiVideos15PreviewModel {
|
||||
t.Fatalf("meta model = %q, want %s", meta.Model, xaiVideos15PreviewModel)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildXAIVideosCreateRequestAllowsCustomSeconds(t *testing.T) {
|
||||
rawJSON := []byte(`{"model":"grok-imagine-video","prompt":"a cat playing piano","seconds":"6"}`)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user