feat: add jimeng video official api - #1553
Conversation
WalkthroughThis change introduces a new middleware for handling Jimeng API requests, updates routing to support these requests, and refines how relay modes and task IDs are managed in context and request flow. It ensures proper conversion and routing of Jimeng-specific actions for video generation and result retrieval. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant GinRouter
participant JimengRequestConvert
participant TokenAuth
participant Distribute
participant RelayTask
Client->>GinRouter: POST /jimeng/?Action=...
GinRouter->>JimengRequestConvert: Request intercepted
JimengRequestConvert->>JimengRequestConvert: Parse Action, mutate body/context
JimengRequestConvert->>GinRouter: Continue
GinRouter->>TokenAuth: Authenticate
TokenAuth->>Distribute: Distribute request
Distribute->>RelayTask: Handle video generation or fetch by ID
RelayTask-->>Client: Response
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15 minutes Possibly related PRs
Suggested reviewers
Poem
Note 🔌 MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
relay/relay_task.go (1)
260-264: Guard against empty task_id earlyIf both sources are empty, fail fast with a 400 to avoid unnecessary DB calls and clearer error semantics.
func videoFetchByIDRespBodyBuilder(c *gin.Context) (respBody []byte, taskResp *dto.TaskError) { taskId := c.Param("task_id") if taskId == "" { taskId = c.GetString("task_id") } + if taskId == "" { + return nil, service.TaskErrorWrapperLocal(errors.New("missing task_id"), "invalid_request", http.StatusBadRequest) + } userId := c.GetInt("id")router/video-router.go (1)
27-33: Prefix group path with slash for consistencyElsewhere you use a leading slash (e.g., "/kling/v1"). Recommend aligning this for consistency and to avoid subtle path joining surprises.
- jimengOfficialGroup := router.Group("jimeng") + jimengOfficialGroup := router.Group("/jimeng")
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
middleware/distributor.go(1 hunks)middleware/jimeng_adapter.go(1 hunks)relay/relay_task.go(1 hunks)router/video-router.go(1 hunks)
🔇 Additional comments (3)
relay/relay_task.go (1)
261-263: Good fallback for task_id sourceUsing context as a fallback when the route param is absent is correct and aligns with the middleware rewrite flow.
middleware/distributor.go (1)
177-179: Do not override pre-set relay_modeConditionally setting relay_mode preserves upstream intent from JimengRequestConvert. This prevents mismatches in fetch-by-id routing.
middleware/jimeng_adapter.go (1)
59-63: Method/path rewrite is compatible with downstream middlewaresChanging Method to GET and Path to /v1/video/generations/:task_id is correct for internal routing. Good call on setting relay_mode and task_id in context.
| action := c.Query("Action") | ||
| if action == "" { | ||
| abortWithOpenAiMessage(c, http.StatusBadRequest, "Action query parameter is required") | ||
| return | ||
| } | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Validate Action against allowed values (and optionally Version)
Restrict Action to the official set to fail fast on unsupported requests. Optionally validate Version if the API requires strict versioning.
action := c.Query("Action")
if action == "" {
abortWithOpenAiMessage(c, http.StatusBadRequest, "Action query parameter is required")
return
}
+ allowed := map[string]bool{
+ "CVSync2AsyncSubmitTask": true,
+ "CVSync2AsyncGetResult": true,
+ }
+ if !allowed[action] {
+ abortWithOpenAiMessage(c, http.StatusBadRequest, "unsupported Action")
+ return
+ }
+ // Optionally enforce version compatibility
+ // if v := c.Query("Version"); v != "2022-08-31" {
+ // abortWithOpenAiMessage(c, http.StatusBadRequest, "unsupported Version")
+ // return
+ // }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| action := c.Query("Action") | |
| if action == "" { | |
| abortWithOpenAiMessage(c, http.StatusBadRequest, "Action query parameter is required") | |
| return | |
| } | |
| action := c.Query("Action") | |
| if action == "" { | |
| abortWithOpenAiMessage(c, http.StatusBadRequest, "Action query parameter is required") | |
| return | |
| } | |
| allowed := map[string]bool{ | |
| "CVSync2AsyncSubmitTask": true, | |
| "CVSync2AsyncGetResult": true, | |
| } | |
| if !allowed[action] { | |
| abortWithOpenAiMessage(c, http.StatusBadRequest, "unsupported Action") | |
| return | |
| } | |
| // Optionally enforce version compatibility | |
| // if v := c.Query("Version"); v != "2022-08-31" { | |
| // abortWithOpenAiMessage(c, http.StatusBadRequest, "unsupported Version") | |
| // return | |
| // } |
🤖 Prompt for AI Agents
In middleware/jimeng_adapter.go around lines 16 to 21, the Action query
parameter is checked only for presence but not validated against allowed values.
Update the code to define a set or list of allowed Action values and verify that
the provided Action matches one of these. If it does not, respond with an
appropriate error and abort. Optionally, add similar validation for the Version
parameter if strict versioning is required by the API.
| model, _ := originalReq["req_key"].(string) | ||
| prompt, _ := originalReq["prompt"].(string) | ||
|
|
||
| unifiedReq := map[string]interface{}{ | ||
| "model": model, | ||
| "prompt": prompt, | ||
| "metadata": originalReq, | ||
| } | ||
|
|
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Confirm mapping of req_key to model
You populate model from req_key. Verify req_key indeed corresponds to the routing model slug used by Distribute/channel selection; otherwise model-based channel selection may fail. If req_key is not a model slug, introduce a mapping or set a stable Jimeng model name.
Would you like me to add a mapping layer or set a default Jimeng model slug?
🏁 Script executed:
#!/bin/bash
# Inspect whether a Jimeng platform/model slug exists and how model is used for channel selection.
rg -n --line-number $'TaskPlatformJimeng|Jimeng' || true
rg -n --line-number $'RelayModeVideoSubmit|RelayModeVideoFetchByID' relay || true
rg -n --line-number $'CoverTaskActionToModelName' one-api | sed -n '1,200p'
rg -n --line-number $'CacheGetRandomSatisfiedChannel|GetModelPrice|FormatMatchingModelName' one-api || trueLength of output: 2939
Ensure req_key Maps to a Valid Jimeng Model Slug
We currently populate the model field directly from originalReq["req_key"] (middleware/jimeng_adapter.go:28–36), but no lookup or transformation is applied. If your internal req_key values don’t exactly match Jimeng’s model slugs, channel selection will break.
Please update one of the following:
- Introduce a mapping table from your
req_keyvalues → Jimeng model names. - Provide a sensible default Jimeng model slug when
req_keyis absent or unrecognized.
[middleware/jimeng_adapter.go:28–36]
🤖 Prompt for AI Agents
In middleware/jimeng_adapter.go around lines 28 to 36, the code assigns the
model field directly from originalReq["req_key"] without validating or mapping
it to a valid Jimeng model slug. To fix this, introduce a mapping from internal
req_key values to Jimeng model slugs and use it to set the model field.
Additionally, provide a sensible default Jimeng model slug if req_key is missing
or unrecognized to ensure channel selection works correctly.
| if image, ok := originalReq["image"]; !ok || image == "" { | ||
| c.Set("action", constant.TaskActionTextGenerate) | ||
| } |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Avoid setting a text-generation action for a video task
Setting action to TaskActionTextGenerate may misclassify video submissions and skew action→model resolution. Prefer a video-specific action (e.g., text2video/image2video) if available, or let the adaptor set it during validation.
Please confirm available video action constants and usages:
🏁 Script executed:
#!/bin/bash
rg -n --line-number $'TaskAction.*Video|TaskActionTextGenerate' one-api || true
rg -n --line-number $'CoverTaskActionToModelName\\(.*\\)' one-api || trueLength of output: 247
Here’s a broader search across the entire repo to locate any video‐related action constants and the mapping function:
🏁 Script executed:
#!/bin/bash
# 1. Find where TaskActionTextGenerate is defined or used
rg -n 'TaskActionTextGenerate'
# 2. Look for any TaskAction constants that include “Video”
rg -n 'TaskAction.*Video'
# 3. Locate the CoverTaskActionToModelName function (definition and calls)
rg -n 'CoverTaskActionToModelName'Length of output: 831
Let’s pull the exact list of TaskAction constants and see how CoverTaskActionToModelName handles them:
🏁 Script executed:
#!/bin/bash
# 1. List all TaskAction constants
rg -n 'TaskAction[A-Za-z0-9_]*' constant/task.go
# 2. Show the body of CoverTaskActionToModelName for mapping logic
rg -n -A20 'func CoverTaskActionToModelName' service/task.goLength of output: 368
Introduce or handle a video-specific action constant in the adapter
Currently, constant/task.go only defines:
TaskActionGenerate = "generate"TaskActionTextGenerate = "textGenerate"
No video-specific action exists, so setting
c.Set("action", constant.TaskActionTextGenerate)for a payload containing "video" yields "vidu_textgenerate" in
CoverTaskActionToModelName(platform, action)and will misroute video tasks to text models.
Please update the code as follows:
• In constant/task.go, add a video action constant, for example:
// TaskActionTextToVideo triggers text→video generation
TaskActionTextToVideo = "textToVideo"• In middleware/jimeng_adapter.go (around lines 47–49), detect video first and set the new constant:
- if image, ok := originalReq["image"]; !ok || image == "" {
- c.Set("action", constant.TaskActionTextGenerate)
- }
+ if _, hasVideo := originalReq["video"]; hasVideo {
+ c.Set("action", constant.TaskActionTextToVideo)
+ } else if image, ok := originalReq["image"]; !ok || image == "" {
+ c.Set("action", constant.TaskActionTextGenerate)
+ }This ensures CoverTaskActionToModelName produces vidu_textToVideo (or similar) and routes to the correct video model.
🤖 Prompt for AI Agents
In middleware/jimeng_adapter.go around lines 47 to 49, the code sets the action
to TaskActionTextGenerate even when the payload contains a video, causing video
tasks to be misrouted to text models. To fix this, first add a new constant
TaskActionTextToVideo in constant/task.go to represent video-specific actions.
Then update the adapter code to detect if the payload contains a video and set
the action to this new constant instead of TaskActionTextGenerate. This will
ensure CoverTaskActionToModelName returns the correct model name for video
tasks.
| c.Set("action", constant.TaskActionTextGenerate) | ||
| } | ||
|
|
||
| c.Request.URL.Path = "/v1/video/generations" |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Set platform context to ensure correct adaptor selection
Make the platform explicit so RelayTaskSubmit picks the Jimeng adaptor without relying on heuristics.
c.Request.URL.Path = "/v1/video/generations"
+ // Ensure adaptor selection picks Jimeng implementation
+ // Note: confirm the constant name in your codebase.
+ // c.Set("platform", string(constant.TaskPlatformJimeng))Verify the platform constant exists:
🏁 Script executed:
#!/bin/bash
rg -n --line-number $'TaskPlatformJimeng' one-api || trueLength of output: 103
The previous search targeted a non-existent directory. Let’s search the entire repository for the Jimeng constant:
🏁 Script executed:
#!/bin/bash
# 1. Look specifically for TaskPlatformJimeng
rg -n "TaskPlatformJimeng" || echo ">> No exact match for TaskPlatformJimeng"
# 2. List all TaskPlatform constants to find the correct name
rg -n "TaskPlatform" -A 2Length of output: 4887
Define and apply TaskPlatformJimeng for explicit adaptor selection
Our search indicates TaskPlatformJimeng isn’t defined, so setting it will fail. Please:
- In
constant/task.go, add the new constant:type TaskPlatform string const ( TaskPlatformSuno TaskPlatform = "suno" TaskPlatformMidjourney = "mj" + TaskPlatformJimeng TaskPlatform = "jimeng" ) - In
middleware/jimeng_adapter.go, set the platform before rerouting:c.Request.URL.Path = "/v1/video/generations" + // Explicitly select the Jimeng adaptor + c.Set("platform", string(constant.TaskPlatformJimeng))
Confirm that "jimeng" matches the intended platform identifier.
🤖 Prompt for AI Agents
In middleware/jimeng_adapter.go at line 51, you set the platform without
defining TaskPlatformJimeng. First, define TaskPlatformJimeng as a constant
string "jimeng" in constant/task.go. Then, in middleware/jimeng_adapter.go
before changing the URL path, assign c.Request.Context or relevant request field
to TaskPlatformJimeng to explicitly mark the platform. This ensures the platform
is correctly identified before rerouting.
…ficail-api feat: add jimeng video official api
增加即梦官方接口
url= 'https://xxx/jimeng/?Action=CVSync2AsyncSubmitTask&Version=2022-08-31'
json {
"aspect_ratio": "16:9",
"prompt": "一只猫在花园里弹钢琴",
"req_key": "jimeng_vgfm_t2v_l20",
"seed": -1
}
url = 'https://xxx/jimeng/?Action=CVSync2AsyncGetResult&Version=2022-08-31'
json {
"task_id": "10874234309578611716"
}
Summary by CodeRabbit
New Features
Bug Fixes