Skip to content

Conversation

@feitianbubu
Copy link
Contributor

@feitianbubu feitianbubu commented Jun 17, 2025

增加可灵视频渠道, 已修改为所有逻辑内聚在new-api内, 使用和suno一致的任务提交和查询逻辑, 可灵渠道按任务接口实现为一个适配器, 后期其他视频渠道可按目录实现适配器

  1. 添加渠道, 下拉菜单选可灵, 可灵的key需要两个值{id},{key}, 目前用逗号分隔, 可考虑优化
    727f36cd-e7dc-43c9-8b34-1fd4e51c2d3c
  2. 提交成功后, 后台自动查询, 任务日志可查看结果, 成功后, 可在详情点击预览视频
    d34743d3fbfbcbdf120c4e3796e6cd6d

Summary by CodeRabbit

  • New Features

    • Added support for the "Kling" video generation platform, enabling task submission, status fetching, and result preview.
    • Introduced new API endpoints for video generation requests and task status retrieval.
    • Integrated video-related routes with authentication and request distribution middleware.
    • Enhanced task logs table with a clickable preview link for generated videos and updated details display.
    • Added "Kling" as a selectable channel option in the user interface.
  • Improvements

    • Updated task log visuals to better represent video generation tasks and the Kling platform.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 17, 2025

Walkthrough

The changes introduce support for a new video generation platform called "Kling" across both backend and frontend components. Backend updates include new constants, DTOs, router endpoints, relay modes, adaptors, and controller logic for handling Kling video tasks. The frontend is updated to display Kling tasks and preview generated video results.

Changes

Files/Group Change Summary
common/constants.go, constant/task.go, relay/constant/relay_mode.go, relay/relay_adaptor.go Added Kling platform/channel constants and relay modes; registered Kling in adaptor factory.
controller/task.go, controller/task_video.go Added and implemented handler for updating Kling video tasks.
controller/relay.go, relay/relay_task.go, middleware/distributor.go Integrated Kling relay modes into request handling, submission, and fetch logic.
relay/channel/adapter.go, relay/channel/task/kling/adaptor.go, relay/channel/task/suno/adaptor.go Extended TaskAdaptor interface; implemented Kling video task adaptor; stubbed ParseResultUrl for Suno.
dto/video.go Added DTOs for video request/response structures.
router/main.go, router/video-router.go Registered video routes and handlers for Kling video tasks.
web/src/components/table/TaskLogsTable.js Added Kling platform and video preview support in task logs table.
web/src/constants/channel.constants.js Added Kling as a selectable channel option.
controller/channel-test.go Added unsupported test error for Kling channel type.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend
    participant Backend
    participant KlingAPI

    User->>Frontend: Submit video generation request
    Frontend->>Backend: POST /v1/video/generations
    Backend->>KlingAPI: Submit video generation (with JWT)
    KlingAPI-->>Backend: Responds with task ID
    Backend-->>Frontend: Responds with task ID

    User->>Frontend: Check video task status
    Frontend->>Backend: GET /v1/video/generations/:task_id
    Backend->>KlingAPI: Fetch task status (with JWT)
    KlingAPI-->>Backend: Responds with task status/result
    Backend-->>Frontend: Returns video status/result
Loading

Poem

(\(\
( -.-) Kling hops in, a video dream,
(")_(") With routes and tags, a brand new theme.

Tasks now sparkle, logs preview too,
A bunny's delight—something fresh to view!

🥕✨🎬

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
relay/channel/task/kling/adaptor.go (1)

172-199: Repeated token-fallback issue in FetchTask

Same security concern: on JWT generation failure the secret key string is sent upstream. Remove the fallback as above.

🧹 Nitpick comments (6)
controller/task_video.go (2)

30-41: Bulk-failure branch ignores database error

If model.TaskBulkUpdate itself returns an error it is only logged to SysError; the outer function still returns success causing the caller to believe the failure path was handled.

Return a wrapped error instead so the caller can retry / alert.


42-45: Hard-coded platform ties controller to one adaptor

relay.GetTaskAdaptor(constant.TaskPlatformKling) locks this controller to Kling only.
If another video platform is added you’ll need an almost identical controller. Pass the platform as a parameter or look it up from channel.Type to keep this generic.

relay/channel/task/kling/adaptor.go (4)

213-229: Metadata field is ignored

SubmitReq exposes a metadata map but convertToRequestPayload drops it.
Either propagate it or remove the field to avoid misleading API consumers.


149-170: Adaptor writes HTTP response – violates separation of concerns

DoResponse both returns (taskID, taskData) and calls c.JSON(...). The caller (relay controller) is likely to write its own response, risking duplicate headers/body.

Return the data only; let the higher layer decide how to respond.


266-272: createJWTTokenWithKey silently accepts malformed input

It just splits on the first comma and returns “invalid format” only when the count ≠ 2.
Validate that both pieces are non-empty to avoid generating tokens with empty iss or secret.


289-312: Nil-safe navigation needed in ParseResultUrl

Multiple unchecked type assertions can panic when upstream schema changes. Prefer the maputil pattern or successive ok checks with early returns to keep the adaptor robust.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d7168c5 and 67fd1d6.

📒 Files selected for processing (17)
  • common/constants.go (2 hunks)
  • constant/task.go (1 hunks)
  • controller/relay.go (1 hunks)
  • controller/task.go (1 hunks)
  • controller/task_video.go (1 hunks)
  • dto/video.go (1 hunks)
  • middleware/distributor.go (1 hunks)
  • relay/channel/adapter.go (1 hunks)
  • relay/channel/task/kling/adaptor.go (1 hunks)
  • relay/channel/task/suno/adaptor.go (1 hunks)
  • relay/constant/relay_mode.go (2 hunks)
  • relay/relay_adaptor.go (2 hunks)
  • relay/relay_task.go (4 hunks)
  • router/main.go (1 hunks)
  • router/video-router.go (1 hunks)
  • web/src/components/table/TaskLogsTable.js (6 hunks)
  • web/src/constants/channel.constants.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (15)
  • router/main.go
  • constant/task.go
  • relay/channel/task/suno/adaptor.go
  • controller/relay.go
  • relay/relay_adaptor.go
  • web/src/constants/channel.constants.js
  • middleware/distributor.go
  • controller/task.go
  • relay/channel/adapter.go
  • router/video-router.go
  • common/constants.go
  • relay/constant/relay_mode.go
  • dto/video.go
  • relay/relay_task.go
  • web/src/components/table/TaskLogsTable.js
🧰 Additional context used
🧬 Code Graph Analysis (1)
relay/channel/task/kling/adaptor.go (6)
relay/channel/adapter.go (1)
  • TaskAdaptor (30-49)
relay/channel/task/suno/adaptor.go (1)
  • TaskAdaptor (21-23)
relay/common/relay_info.go (1)
  • TaskRelayInfo (272-278)
service/error.go (2)
  • TaskErrorWrapperLocal (134-138)
  • TaskErrorWrapper (140-156)
relay/channel/api_request.go (1)
  • DoTaskApiRequest (252-274)
service/http_client.go (1)
  • GetHttpClient (32-34)

Comment on lines 100 to 107
case "submitted", "queued":
task.Status = model.TaskStatusSubmitted
case "processing":
task.Status = model.TaskStatusInProgress
case "succeed":
task.Status = model.TaskStatusSuccess
task.Progress = "100%"
if url, err := adaptor.(interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Progress never advances for “submitted/queued/processing” states

task.Progress is updated only on success/failure. For long-running video renders the UI will always show whatever stale value was written at submission time (often "").

Consider setting a rough percentage, e.g.
• queued → 0%
• processing → value returned by upstream if available, or 50%/80%.

🤖 Prompt for AI Agents
In controller/task_video.go around lines 100 to 107, the task.Progress field is
only updated for success or failure states, causing the UI to show stale
progress for submitted, queued, and processing states. To fix this, set
task.Progress to "0%" for the queued state, and for processing, update
task.Progress with a value returned by the upstream source if available, or
default to a reasonable estimate like "50%" or "80%". This ensures the UI
reflects ongoing progress more accurately.

Comment on lines +124 to +132
if task.Status == model.TaskStatusFailure {
common.LogInfo(ctx, fmt.Sprintf("Task %s failed: %s", task.TaskID, task.FailReason))
quota := task.Quota
if quota != 0 {
if err := model.IncreaseUserQuota(task.UserId, quota, false); err != nil {
common.LogError(ctx, "Failed to increase user quota: "+err.Error())
}
logContent := fmt.Sprintf("Video async task failed %s, refund %s", task.TaskID, common.LogQuota(quota))
model.RecordLog(task.UserId, model.LogTypeSystem, logContent)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Potential double-refund on repeated polling

When a task is permanently marked FAILURE you refund quota each time this poller runs. Nothing prevents the same failed task from being re-evaluated on the next scheduler tick, issuing multiple refunds.

Persist a “refunded” flag or guard with if task.Status == FAILURE && !task.Refunded.

🤖 Prompt for AI Agents
In controller/task_video.go around lines 124 to 134, the code refunds user quota
every time a task with status FAILURE is processed, causing potential double
refunds on repeated polls. To fix this, add a "refunded" flag to the task model
and update the condition to check that the task is FAILURE and not yet refunded
before issuing a refund. After successfully refunding, set the refunded flag to
true and persist this change to prevent multiple refunds for the same task.

Comment on lines 98 to 111
if status, ok := data["task_status"].(string); ok {
switch status {
case "submitted", "queued":
task.Status = model.TaskStatusSubmitted
case "processing":
task.Status = model.TaskStatusInProgress
case "succeed":
task.Status = model.TaskStatusSuccess
task.Progress = "100%"
if url, err := adaptor.(interface {
ParseResultUrl(map[string]any) (string, error)
}).ParseResultUrl(responseItem); err == nil {
task.FailReason = url
} else {
common.LogWarn(ctx, fmt.Sprintf("Failed to get url from body for task %s: %s", task.TaskID, err.Error()))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Do not overload FailReason with success information

The successful-task branch stores the result video URL in task.FailReason.
That field semantically represents an error; overloading it with the result makes downstream code and UI very confusing and forces callers to branch on both Status and the meaning of FailReason.

-			if url, err := adaptor.(interface {
-				ParseResultUrl(map[string]any) (string, error)
-			}).ParseResultUrl(responseItem); err == nil {
-				task.FailReason = url     // <- misuse
-			} else {
+			if url, err := adaptor.(interface {
+				ParseResultUrl(map[string]any) (string, error)
+			}).ParseResultUrl(responseItem); err == nil {
+				task.ResultUrl = url      // add a dedicated column / json field
+			} else {

Please add a dedicated field such as ResultUrl (string) to model.Task and persist that instead.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In controller/task_video.go around lines 98 to 113, the code incorrectly stores
the result video URL in the FailReason field, which should only represent
errors. To fix this, add a new string field named ResultUrl to the model.Task
struct and assign the parsed URL to this new field instead of FailReason in the
success case. This will keep error and success data separate and avoid confusion
in downstream code and UI.

Comment on lines +81 to +99
func (a *TaskAdaptor) ValidateRequestAndSetAction(c *gin.Context, info *relaycommon.TaskRelayInfo) (taskErr *dto.TaskError) {
// Accept only POST /v1/video/generations as "generate" action.
action := "generate"
info.Action = action

var req SubmitReq
if err := common.UnmarshalBodyReusable(c, &req); err != nil {
taskErr = service.TaskErrorWrapperLocal(err, "invalid_request", http.StatusBadRequest)
return
}
if strings.TrimSpace(req.Prompt) == "" {
taskErr = service.TaskErrorWrapperLocal(fmt.Errorf("prompt is required"), "invalid_request", http.StatusBadRequest)
return
}

// Store into context for later usage
c.Set("kling_request", req)
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

HTTP method/path are not validated

ValidateRequestAndSetAction assumes every request hitting this adaptor is POST /v1/video/generations.
A malformed route (e.g. GET) will slip through and produce upstream 405/404 errors.

Check verb & path and return a TaskError early.

🤖 Prompt for AI Agents
In relay/channel/task/kling/adaptor.go around lines 81 to 99, the function
ValidateRequestAndSetAction does not verify the HTTP method and path, assuming
all requests are POST /v1/video/generations. To fix this, add checks at the
start of the function to confirm the request method is POST and the path matches
/v1/video/generations; if not, return a TaskError with an appropriate error code
and message to prevent malformed requests from proceeding.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
controller/task_video.go (3)

98-106: Progress never advances for “submitted/queued/processing” states

task.Progress is only set on success. For long-running renders the UI will keep whatever stale value was written at submission time (often empty).

Please initialise sensible percentages (e.g. 0%, 50%, …) or propagate the upstream value for these intermediate states.


107-110: Do not overload FailReason with success data

Storing the result URL in task.FailReason blurs the field’s purpose and complicates downstream logic.

-				task.FailReason = url
+				task.ResultURL  = url // add a dedicated column / json tag

121-132: Potential double-refund on repeated polling

Each scheduler pass refunds quota for any FAILURE task. Without a guard, users can receive multiple refunds for the same task.

Add a Refunded flag (or similar) and guard the block:

-	if task.Status == model.TaskStatusFailure {
+	if task.Status == model.TaskStatusFailure && !task.Refunded {
 		...
+		task.Refunded = true
+		_ = task.Update()
 	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67fd1d6 and bbdbe61.

📒 Files selected for processing (2)
  • controller/task_video.go (1 hunks)
  • relay/channel/task/kling/adaptor.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • relay/channel/task/kling/adaptor.go

Comment on lines +42 to +45
adaptor := relay.GetTaskAdaptor(constant.TaskPlatformKling)
if adaptor == nil {
return fmt.Errorf("video adaptor not found")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Hard-coded adaptor locks the controller to Kling only

relay.GetTaskAdaptor(constant.TaskPlatformKling) forces every channel—regardless of its actual type—to be handled with the Kling adaptor. As soon as another video platform is added, those tasks will be mis-processed or fail outright.

-	adaptor := relay.GetTaskAdaptor(constant.TaskPlatformKling)
+	// Select adaptor based on the channel’s platform/type.
+	adaptor := relay.GetTaskAdaptor(channel.Type) // map or switch if names differ
🤖 Prompt for AI Agents
In controller/task_video.go around lines 42 to 45, the code currently hard-codes
the adaptor to Kling by calling relay.GetTaskAdaptor with
constant.TaskPlatformKling, which restricts the controller to only handle Kling
platform tasks. To fix this, modify the code to dynamically select the adaptor
based on the actual platform of the task or channel being processed instead of
using a fixed constant. This may involve passing the platform identifier as a
parameter or retrieving it from the task context before calling GetTaskAdaptor.

@xyfacai
Copy link
Collaborator

xyfacai commented Jun 17, 2025

这种非 Chat 接口渠道,应该要在 Chat 那边拦截住禁止 Chat 调用

@feitianbubu
Copy link
Contributor Author

这种非 Chat 接口渠道,应该要在 Chat 那边拦截住禁止 Chat 调用

有道理, 参考suno把渠道测试那边栏了

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
controller/channel-test.go (1)

43-45: Consolidate duplicated “unsupported channel” guards & unify naming

Four separate if branches now do the exact same thing. Consider:

  1. Replace the repeated checks with a helper like isNonChatChannel(channel.Type) or a switch statement to reduce copy-paste and future merge conflicts.
  2. The message says “kling” while the constant/PR text alternates between “Kling” and “Keling”. Pick one spelling and use it everywhere to avoid confusing logs and UX.
  3. (Optional) When returning sentinel errors, wrapping with %w (or using errors.Join/third-party stack helpers) preserves stack traces for easier debugging.

Example sketch:

- if channel.Type == common.ChannelTypeKling {
-     return errors.New("kling channel test is not supported"), nil
- }
+if isNonChatChannel(channel.Type) {
+    return fmt.Errorf("%s channel test is not supported", channel.Type.String()), nil
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbdbe61 and 4168713.

📒 Files selected for processing (1)
  • controller/channel-test.go (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
controller/channel-test.go (1)
common/constants.go (1)
  • ChannelTypeKling (244-244)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
relay/channel/task/kling/adaptor.go (2)

81-99: HTTP method/path validation still missing.

This method still doesn't validate that the request is actually POST /v1/video/generations as assumed. Malformed requests (e.g., GET requests) will proceed and cause upstream 405/404 errors.


107-118: Security vulnerability: Dangerous JWT fallback still present.

Despite the past review comment indicating this was addressed, the dangerous fallback on line 110 still exists. When JWT creation fails, the raw API key (containing the secret) is used in the Authorization header, which can leak sensitive credentials to logs and proxies.

func (a *TaskAdaptor) BuildRequestHeader(c *gin.Context, req *http.Request, info *relaycommon.TaskRelayInfo) error {
	token, err := a.createJWTToken()
	if err != nil {
-		token = info.ApiKey // fallback
+		return fmt.Errorf("jwt token creation failed: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("User-Agent", "kling-sdk/1.0")
	return nil
}
🧹 Nitpick comments (1)
relay/channel/task/kling/adaptor.go (1)

68-78: Consider adding validation for API key format.

The Init method assumes the API key will be in "access_key,secret_key" format but doesn't validate this assumption. While JWT creation methods validate later, early validation would provide clearer error messages.

func (a *TaskAdaptor) Init(info *relaycommon.TaskRelayInfo) {
	a.ChannelType = info.ChannelType
	a.baseURL = info.BaseUrl

	// apiKey format: "access_key,secret_key"
	keyParts := strings.Split(info.ApiKey, ",")
-	if len(keyParts) == 2 {
+	if len(keyParts) != 2 {
+		// Log warning or handle invalid format
+		return
+	}
		a.accessKey = strings.TrimSpace(keyParts[0])
		a.secretKey = strings.TrimSpace(keyParts[1])
-	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4168713 and 1cd7c2e.

📒 Files selected for processing (17)
  • common/constants.go (2 hunks)
  • constant/task.go (1 hunks)
  • controller/relay.go (1 hunks)
  • controller/task.go (1 hunks)
  • controller/task_video.go (1 hunks)
  • dto/video.go (1 hunks)
  • middleware/distributor.go (1 hunks)
  • relay/channel/adapter.go (1 hunks)
  • relay/channel/task/kling/adaptor.go (1 hunks)
  • relay/channel/task/suno/adaptor.go (1 hunks)
  • relay/constant/relay_mode.go (2 hunks)
  • relay/relay_adaptor.go (2 hunks)
  • relay/relay_task.go (4 hunks)
  • router/main.go (1 hunks)
  • router/video-router.go (1 hunks)
  • web/src/components/table/TaskLogsTable.js (6 hunks)
  • web/src/constants/channel.constants.js (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • dto/video.go
🚧 Files skipped from review as they are similar to previous changes (15)
  • router/main.go
  • constant/task.go
  • relay/channel/adapter.go
  • web/src/constants/channel.constants.js
  • relay/relay_adaptor.go
  • common/constants.go
  • relay/channel/task/suno/adaptor.go
  • controller/relay.go
  • middleware/distributor.go
  • router/video-router.go
  • controller/task.go
  • relay/constant/relay_mode.go
  • web/src/components/table/TaskLogsTable.js
  • relay/relay_task.go
  • controller/task_video.go
🔇 Additional comments (11)
relay/channel/task/kling/adaptor.go (11)

1-22: Package structure and imports look good.

The package declaration and imports are properly organized and include all necessary dependencies for the Kling adapter implementation.


24-55: Request/response structures are well-defined.

The struct definitions properly model the API request and response formats with appropriate JSON tags and field types.


102-104: URL construction is correct.

The method properly constructs the upstream API URL for video generation.


121-134: Request body construction is well-implemented.

The method properly retrieves the validated request from context, converts it to the upstream format, and handles errors appropriately.


137-170: Response handling methods are robust.

The DoRequest delegation and DoResponse parsing with fallback mechanisms are well-implemented. The dual parsing approach (Kling-specific then generic) provides good error resilience.


201-207: Metadata methods are correctly implemented.

The GetModelList and GetChannelName methods properly return the supported models and channel identifier.


213-229: Request payload conversion is well-implemented.

The conversion logic properly transforms the internal request format to the upstream API format with appropriate default values.


231-256: Helper functions are well-designed.

The aspect ratio mapping and default value functions are simple, clear, and handle edge cases appropriately.


262-287: JWT token creation is properly implemented.

The JWT methods follow security best practices with proper validation, standard claims structure, reasonable expiration times, and secure HS256 signing.


290-312: URL parsing method is robust and safe.

The ParseResultUrl method properly handles the complex nested JSON structure with comprehensive type checking and clear error messages for different failure scenarios.


1-313: Overall implementation is solid but has critical security vulnerabilities.

The Kling adapter is well-structured and implements the required interface properly. However, the JWT fallback mechanisms in BuildRequestHeader and FetchTask methods pose serious security risks by potentially exposing API secrets. These must be fixed before merging.

Key strengths:

  • Clear code organization and separation of concerns
  • Robust error handling in most areas
  • Proper JWT implementation
  • Good request/response handling

Critical issues to address:

  • JWT fallback vulnerabilities (lines 110, 187)
  • Missing HTTP method/path validation (lines 81-99)

Comment on lines +185 to +188
token, err := a.createJWTTokenWithKey(key)
if err != nil {
token = key
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Same JWT fallback vulnerability in FetchTask.

This method has the same dangerous fallback pattern where the raw API key is used if JWT token creation fails, potentially exposing secrets.

	token, err := a.createJWTTokenWithKey(key)
	if err != nil {
-		token = key
+		return nil, fmt.Errorf("jwt token creation failed: %w", err)
	}
📝 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.

Suggested change
token, err := a.createJWTTokenWithKey(key)
if err != nil {
token = key
}
// … other code …
token, err := a.createJWTTokenWithKey(key)
if err != nil {
return nil, fmt.Errorf("jwt token creation failed: %w", err)
}
// … remaining code …
🤖 Prompt for AI Agents
In relay/channel/task/kling/adaptor.go around lines 185 to 188, the code falls
back to using the raw API key if JWT token creation fails, which risks exposing
sensitive secrets. Remove the fallback assignment of token to key on error.
Instead, handle the error properly by returning it or logging it without using
the raw key as a token, ensuring no secret leakage occurs.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
controller/channel-test.go (1)

43-45: LGTM! Consistent implementation for blocking Kling channel testing.

The implementation correctly prevents testing of the Kling channel type, following the established pattern for other non-Chat interface channels like Suno. This aligns with the PR objectives of ensuring proper separation between Chat and non-Chat channels.

Minor observation: Consider standardizing error message formats across all channel types for consistency (e.g., "midjourney plus channel test is not supported!!!" has extra exclamation marks while others don't).

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1cd7c2e and 616e695.

📒 Files selected for processing (18)
  • common/constants.go (2 hunks)
  • constant/task.go (1 hunks)
  • controller/channel-test.go (1 hunks)
  • controller/relay.go (1 hunks)
  • controller/task.go (1 hunks)
  • controller/task_video.go (1 hunks)
  • dto/video.go (1 hunks)
  • middleware/distributor.go (1 hunks)
  • relay/channel/adapter.go (1 hunks)
  • relay/channel/task/kling/adaptor.go (1 hunks)
  • relay/channel/task/suno/adaptor.go (1 hunks)
  • relay/constant/relay_mode.go (2 hunks)
  • relay/relay_adaptor.go (2 hunks)
  • relay/relay_task.go (4 hunks)
  • router/main.go (1 hunks)
  • router/video-router.go (1 hunks)
  • web/src/components/table/TaskLogsTable.js (6 hunks)
  • web/src/constants/channel.constants.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
  • controller/task.go
  • router/main.go
  • constant/task.go
  • web/src/constants/channel.constants.js
  • controller/relay.go
  • relay/channel/task/suno/adaptor.go
  • relay/channel/adapter.go
  • common/constants.go
  • relay/relay_adaptor.go
  • middleware/distributor.go
  • router/video-router.go
  • dto/video.go
  • web/src/components/table/TaskLogsTable.js
  • relay/constant/relay_mode.go
  • relay/relay_task.go
  • controller/task_video.go
  • relay/channel/task/kling/adaptor.go

@Calcium-Ion Calcium-Ion changed the title Feat/video feat: 支持可灵视频渠道(异步任务) Jun 20, 2025
@Calcium-Ion Calcium-Ion merged commit 5baaa06 into QuantumNous:alpha Jun 20, 2025
1 check passed
@coderabbitai coderabbitai bot mentioned this pull request Jul 30, 2025
@feitianbubu feitianbubu deleted the feat/video branch August 13, 2025 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants