Skip to content

feat: add MiniMax H3 video generation - #6591

Open
twodogegg wants to merge 2 commits into
QuantumNous:mainfrom
twodogegg:codex/minimax-video-v2
Open

feat: add MiniMax H3 video generation#6591
twodogegg wants to merge 2 commits into
QuantumNous:mainfrom
twodogegg:codex/minimax-video-v2

Conversation

@twodogegg

@twodogegg twodogegg commented Aug 1, 2026

Copy link
Copy Markdown

⚠️ 提交说明 / PR Notice

Important

  • 请提供人工撰写的简洁摘要,避免直接粘贴未经整理的 AI 输出。

📝 变更描述 / Description

新增 MiniMax Video Generation V2(MiniMax-H3)任务适配器,支持 /v1/videos 提交、多模态内容校验、V2 任务状态轮询和 OpenAI Video 响应转换。

同一 MiniMax 渠道会根据映射后的上游模型选择 V1 或 V2 任务平台,并将平台写入任务记录,确保后台轮询继续使用正确协议。计费按官方秒价预扣;参考视频按最大输入时长预留,任务完成后依据上游 usage 安全结算,并记录额度饱和审计信息。远程媒体的格式、大小及尺寸等内容属性仍由 MiniMax 上游校验。

本变更由 AI 辅助实现,并经过本地测试与代码规范检查。

🚀 变更类型 / Type of change

  • 🐛 Bug 修复 (Bug fix) - 请关联对应 Issue,避免将设计取舍、理解偏差或预期不一致直接归类为 bug
  • ✨ 新功能 (New feature) - 重大特性建议先通过 Issue 沟通
  • ⚡ 性能优化 / 重构 (Refactor)
  • 📝 文档更新 (Documentation)

🔗 关联任务 / Related Issue

✅ 提交前检查项 / Checklist

  • 人工确认: 我已亲自整理并撰写此描述,没有直接粘贴未经处理的 AI 输出。
  • 非重复提交: 我已搜索现有的 IssuesPRs,确认不是重复提交。
  • Bug fix 说明: 若此 PR 标记为 Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。
  • 变更理解: 我已理解这些更改的工作原理及可能影响。
  • 范围聚焦: 本 PR 未包含任何与当前任务无关的代码改动。
  • 本地验证: 已在本地运行并通过测试或手动验证,维护者可以据此复核结果。
  • 安全合规: 代码中无敏感凭据,且符合项目代码规范。

📸 运行证明 / Proof of Work

以下命令均在本地通过:

  • make test
  • GOWORK=off go vet ./...
  • GOWORK=off go build ./...
  • cd relaykit && GOWORK=off go vet ./...
  • cd relaykit && GOWORK=off go build ./...

新增回归测试覆盖 V2 请求校验与上游转换、异步查询状态和结果 URL、MiniMax V1/V2 平台选择,以及完成任务后的计费结算。

Summary by CodeRabbit

  • New Features

    • Added MiniMax-H3 video generation support through the Hailuo V2 integration.
    • Added video task creation, status tracking, result conversion, validation, and model routing.
    • Added MiniMax-H3 to the supported model list with default pricing.
  • Billing

    • Improved completion-based billing, including quota adjustments and usage-based pricing for video inputs.
  • Bug Fixes

    • Billing settlement now correctly respects whether a task requires completion-time adjustment.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

MiniMax Hailuo V2 integration

Layer / File(s) Summary
Platform contracts and routing
constant/task.go, relay/channel/minimax/*, relay/channel/task/hailuo_v2/models.go, relay/relay_adaptor.go, relay/relay_task.go
Adds the MiniMax V2 platform, Hailuo V2 API models, MiniMax-H3 registration, adaptor dispatch, and model-based task routing.
Hailuo V2 task execution
relay/channel/task/hailuo_v2/*
Adds request validation, authenticated task creation, polling, response parsing, OpenAI video conversion, and integration tests.
Completion billing settlement
relay/channel/adapter.go, relay/channel/task/hailuo_v2/adaptor.go, service/task_polling.go, service/task_billing_test.go, controller/relay.go, setting/ratio_setting/model_ratio.go
Adds completion billing, usage-based quota adjustment, quota-clamp logging, settlement guards, and default model pricing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant RelayTask
  participant HailuoV2TaskAdaptor
  participant MiniMaxAPI
  participant TaskPolling
  Client->>RelayTask: Submit MiniMax-H3 video task
  RelayTask->>HailuoV2TaskAdaptor: Validate and build task request
  HailuoV2TaskAdaptor->>MiniMaxAPI: Create video task
  MiniMaxAPI-->>HailuoV2TaskAdaptor: Return upstream task ID
  TaskPolling->>HailuoV2TaskAdaptor: Fetch task status
  HailuoV2TaskAdaptor->>MiniMaxAPI: Poll upstream task
  MiniMaxAPI-->>TaskPolling: Return task status and video result
  TaskPolling-->>Client: Return OpenAI video response
Loading

Possibly related PRs

Suggested reviewers: calcium-ion

Poem

A rabbit submits a video task,
Hailuo validates each request.
MiniMax returns the task state,
Billing settles when usage is complete.
Quota clamps enter the log,
And the relay returns the result.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding MiniMax H3 video generation support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
service/task_billing_test.go (1)

872-885: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Give the legacy mock a distinct non-zero quota to prove precedence.

mockAdaptor{} leaves adjustReturn at 0, so the legacy path returns 0. The test name states that the checked result takes priority, but the assertion cannot distinguish precedence from the legacy path simply returning nothing. Set a different non-zero legacy value.

♻️ Proposed test change
 	task := makeTask(userID, channelID, preConsumed, tokenID, BillingSourceWallet, 0)
 	adaptor := &checkedMockAdaptor{
-		mockAdaptor:   &mockAdaptor{},
+		mockAdaptor:   &mockAdaptor{adjustReturn: 4000},
 		checkedReturn: actualQuota,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@service/task_billing_test.go` around lines 872 - 885, Update the test setup
around checkedMockAdaptor to assign mockAdaptor.adjustReturn a distinct non-zero
quota different from actualQuota, then retain the existing assertion that
task.Quota equals actualQuota to verify the checked result takes precedence over
the legacy result.
relay/channel/task/hailuo_v2/adaptor.go (1)

328-346: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Log the fallback when upstream usage is unavailable.

Every early return yields 0, so settlement keeps the pre-reserved quota. For a request with a reference video, that reservation includes maxReferenceInputSeconds (15s), so the user pays the worst case whenever task.Data fails to parse or TotalSeconds is zero. Add a log line on these paths so operators can detect silent overcharges.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@relay/channel/task/hailuo_v2/adaptor.go` around lines 328 - 346, Update
AdjustBillingOnCompleteChecked to log when upstream usage is unavailable before
returning the zero adjustment for task.Data unmarshalling failures or
nonpositive response.Task.Usage.TotalSeconds. Include enough context to identify
the fallback and preserve the existing settlement behavior and other early
returns.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@controller/relay.go`:
- Line 599: Update the PerCallBilling condition in the relay billing flow so
completion-billed tasks with result.SettleOnComplete set do not trigger
submit-time settlement; retain the existing price-patch and UsePrice checks for
tasks settled per call.

In `@relay/channel/task/hailuo_v2/adaptor.go`:
- Around line 63-70: Update validateVideoRequest’s invalid-duration error to
report the computed maxAllowedDuration rather than the hardcoded 15, while
retaining the existing minimum-bound validation and error code.
- Around line 250-272: Update ParseTaskResult to explicitly handle every
additional Hailuo V2 task status returned by the upstream API, mapping each to
the appropriate TaskInfo status and progress; alternatively, ensure the
downstream relay/task_polling flow handles that status without falling through
to an unknown-status error. Preserve the existing mappings for queued, running,
succeeded, failed, cancelled, and expired.

---

Nitpick comments:
In `@relay/channel/task/hailuo_v2/adaptor.go`:
- Around line 328-346: Update AdjustBillingOnCompleteChecked to log when
upstream usage is unavailable before returning the zero adjustment for task.Data
unmarshalling failures or nonpositive response.Task.Usage.TotalSeconds. Include
enough context to identify the fallback and preserve the existing settlement
behavior and other early returns.

In `@service/task_billing_test.go`:
- Around line 872-885: Update the test setup around checkedMockAdaptor to assign
mockAdaptor.adjustReturn a distinct non-zero quota different from actualQuota,
then retain the existing assertion that task.Quota equals actualQuota to verify
the checked result takes precedence over the legacy result.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d9f305c-8a52-4f65-8ae8-48490f5437bf

📥 Commits

Reviewing files that changed from the base of the PR and between 0ab0202 and 4b66096.

📒 Files selected for processing (14)
  • constant/task.go
  • controller/relay.go
  • relay/channel/adapter.go
  • relay/channel/minimax/adaptor_test.go
  • relay/channel/minimax/constants.go
  • relay/channel/task/hailuo_v2/adaptor.go
  • relay/channel/task/hailuo_v2/adaptor_test.go
  • relay/channel/task/hailuo_v2/models.go
  • relay/relay_adaptor.go
  • relay/relay_adaptor_minimax_test.go
  • relay/relay_task.go
  • service/task_billing_test.go
  • service/task_polling.go
  • setting/ratio_setting/model_ratio.go

Comment thread controller/relay.go Outdated
Comment thread relay/channel/task/hailuo_v2/adaptor.go
Comment thread relay/channel/task/hailuo_v2/adaptor.go
@twodogegg

Copy link
Copy Markdown
Author

已核实并处理本轮审查意见(2d4ed91b0):

  • 修正 duration 错误信息,使用实际计算后的上下限。
  • 上游完成用量无法解析或缺失时记录包含任务 ID 的告警,保留安全的预扣回退行为。
  • 将 legacy mock 设为不同的非零额度,真实验证 checked billing 的优先级。
  • 将内部 SettleOnComplete 重命名为 AdjustBillingOnComplete,明确提交时确认预扣、完成时仅做差额调整。
  • 拒绝 callback_url,避免 MiniMax 回调绕过网关泄露上游 task ID。

另外两项经核实无需修改:

  • 提交结算与完成结算不会重复收费;完成阶段只按 actualQuota - task.Quota 补扣或退款。
  • MiniMax 官方 V2 查询文档只定义六种状态,当前实现已经全部覆盖。

本地验证通过:make test、根模块及 relaykit 的 GOWORK=off go vet ./...GOWORK=off go build ./...

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
relay/relay_task.go (1)

149-161: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Define platform selection for action-only task submissions.

RelayTaskSubmit selects platform before info.Action populates info.UpstreamModelName. If c.GetString("platform") can be empty while both info.OriginModelName and info.Action are also empty, GetTaskPlatformForModel returns an empty platform and GetTaskAdaptor returns invalid_api_platform. Require or inject platform before adaptor selection, or derive the action/model first.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@relay/relay_task.go` around lines 149 - 161, Update RelayTaskSubmit so
action-only submissions determine a non-empty platform before GetTaskAdaptor is
called. When the request platform is absent, derive it after info.Action or the
relevant model-population flow has established info.UpstreamModelName; otherwise
require or inject a valid platform and preserve the existing invalid-platform
handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@relay/relay_task.go`:
- Around line 149-161: Update RelayTaskSubmit so action-only submissions
determine a non-empty platform before GetTaskAdaptor is called. When the request
platform is absent, derive it after info.Action or the relevant model-population
flow has established info.UpstreamModelName; otherwise require or inject a valid
platform and preserve the existing invalid-platform handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 19787584-aee3-450c-87d4-284b1910e486

📥 Commits

Reviewing files that changed from the base of the PR and between 4b66096 and 2d4ed91.

📒 Files selected for processing (5)
  • controller/relay.go
  • relay/channel/task/hailuo_v2/adaptor.go
  • relay/channel/task/hailuo_v2/adaptor_test.go
  • relay/relay_task.go
  • service/task_billing_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • service/task_billing_test.go
  • controller/relay.go
  • relay/channel/task/hailuo_v2/adaptor_test.go
  • relay/channel/task/hailuo_v2/adaptor.go

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.

1 participant