Skip to content

feat: proxy MiniMax H3 video generation - #1427

Open
octo-patch wants to merge 1 commit into
ding113:mainfrom
octo-patch:octo/20260812-text-to-video-tool-recvrXOFKFfMj8
Open

feat: proxy MiniMax H3 video generation#1427
octo-patch wants to merge 1 commit into
ding113:mainfrom
octo-patch:octo/20260812-text-to-video-tool-recvrXOFKFfMj8

Conversation

@octo-patch

@octo-patch octo-patch commented Aug 12, 2026

Copy link
Copy Markdown

Reason: MiniMax-H3 video generation requests need native /v2 routing and request validation.

This change exposes the /v2 proxy route, adds video-generation endpoint families, preserves regional upstream paths, and validates the supported text-to-video request schema before forwarding. Focused routing and schema tests cover the new endpoint alongside existing proxy behavior.

Checks:

  • ./node_modules/.bin/biome check src/app/v2/[...route]/route.ts src/app/v1/_lib/proxy/video-generation-v2.ts src/app/v1/_lib/proxy/endpoint-family-catalog.ts src/app/v1/_lib/proxy/forwarder.ts src/proxy.matcher.ts src/proxy.ts tests/unit/proxy-matcher.test.ts tests/unit/proxy/endpoint-family-catalog.test.ts tests/unit/proxy/endpoint-family-provider-routing.test.ts tests/unit/proxy/video-generation-v2.test.ts tests/unit/app/v1/url.test.ts
  • ./node_modules/.bin/vitest run --configLoader bundle tests/unit/proxy/video-generation-v2.test.ts tests/unit/proxy/endpoint-family-catalog.test.ts tests/unit/proxy/endpoint-family-provider-routing.test.ts tests/unit/proxy-matcher.test.ts tests/unit/app/v1/url.test.ts (221 passed)
  • bun run typecheck

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

变更概览

本次变更新增 OpenAI 视频生成 v2 端点支持。系统新增 /v2 路由、端点目录配置和文本请求校验,并补充 URL、匹配器、路由及校验测试。

Changes

视频生成 v2 代理

Layer / File(s) Summary
v2 路由入口与匹配范围
src/app/v2/[...route]/route.ts, src/proxy.matcher.ts, src/proxy.ts, tests/unit/proxy-matcher.test.ts
新增 /v2 Hono 路由,支持多种 HTTP 方法。现有代理匹配器不再匹配 /v2 及其子路径。
视频生成端点目录与路由
src/app/v1/_lib/proxy/endpoint-family-catalog.ts, tests/unit/proxy/endpoint-family-catalog.test.ts, tests/unit/proxy/endpoint-family-provider-routing.test.ts, tests/unit/app/v1/url.test.ts
新增创建、查询和资源端点族。端点使用 openai 格式,并路由至 openai-compatible 提供商。测试覆盖区域 URL 拼接。
文本请求校验与转发
src/app/v1/_lib/proxy/video-generation-v2.ts, src/app/v1/_lib/proxy/forwarder.ts, tests/unit/proxy/video-generation-v2.test.ts
新增文本转视频请求类型和校验器。校验模型、文本内容、提示词长度、分辨率、时长、比例及回调地址。无效请求在转发前返回 400 错误。

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: ding113

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
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.
Title check ✅ Passed 标题准确概括了为 MiniMax H3 增加视频生成代理支持这一主要变更。
Description check ✅ Passed 描述与变更内容相关,说明了 v2 路由、端点族、请求校验和测试覆盖。
✨ 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 requested a review from ding113 August 12, 2026 20:26
accountingTier: "none",
modelRequired: false,
rawPassthrough: false,
match: (pathname) => hasPrefix(pathname, "/v2/query/video_generation"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Query path duplicates base segments

If a provider uses the supported base URL https://api.minimax.io/v2/video_generation, a task query falls through to standard URL concatenation and produces /v2/video_generation/v2/query/video_generation/{task}, causing the upstream request to fail on a nonexistent path.

Knowledge Base Used: Proxy request pipeline

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/app/v1/_lib/proxy/endpoint-family-catalog.ts
Line: 151

Comment:
**Query path duplicates base segments**

If a provider uses the supported base URL `https://api.minimax.io/v2/video_generation`, a task query falls through to standard URL concatenation and produces `/v2/video_generation/v2/query/video_generation/{task}`, causing the upstream request to fail on a nonexistent path.

**Knowledge Base Used:** [Proxy request pipeline](https://app.greptile.com/ygxz/-/custom-context/knowledge-base/ding113/claude-code-hub/-/docs/proxy-pipeline.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@src/app/v1/_lib/proxy/video-generation-v2.ts`:
- Around line 53-89: Update the validation returns in video-generation-v2.ts
around the request checks to use stable validation error codes instead of
hardcoded English messages, while generating localized messages at the response
boundary based on the request language. Update
tests/unit/proxy/video-generation-v2.test.ts lines 25-39 to assert the relevant
error codes rather than English message fragments.
🪄 Autofix

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: cd72d19f-1d7f-4e10-a8a4-ff28a0ff7183

📥 Commits

Reviewing files that changed from the base of the PR and between 5424991 and 7573e79.

📒 Files selected for processing (11)
  • src/app/v1/_lib/proxy/endpoint-family-catalog.ts
  • src/app/v1/_lib/proxy/forwarder.ts
  • src/app/v1/_lib/proxy/video-generation-v2.ts
  • src/app/v2/[...route]/route.ts
  • src/proxy.matcher.ts
  • src/proxy.ts
  • tests/unit/app/v1/url.test.ts
  • tests/unit/proxy-matcher.test.ts
  • tests/unit/proxy/endpoint-family-catalog.test.ts
  • tests/unit/proxy/endpoint-family-provider-routing.test.ts
  • tests/unit/proxy/video-generation-v2.test.ts

Comment on lines +53 to +89
if (body.model !== TEXT_TO_VIDEO_MODEL) {
return fail(`Invalid request: model must be ${TEXT_TO_VIDEO_MODEL}.`);
}

if (!Array.isArray(body.content) || body.content.length !== 1) {
return fail("Invalid request: text-to-video content must contain exactly one text item.");
}

const content = body.content[0];
if (typeof content !== "object" || content === null || Array.isArray(content)) {
return fail("Invalid request: content must be an object.");
}
const textContent = content as Record<string, unknown>;
if (textContent.type !== "text") {
return fail("Invalid request: text-to-video content type must be text.");
}
if (typeof textContent.text !== "string" || textContent.text.trim().length === 0) {
return fail("Invalid request: text-to-video requires a non-empty text prompt.");
}
if (textContent.text.length > 7000) {
return fail("Invalid request: text prompt must not exceed 7000 characters.");
}

if (body.resolution !== TEXT_TO_VIDEO_RESOLUTION) {
return fail(`Invalid request: resolution must be ${TEXT_TO_VIDEO_RESOLUTION}.`);
}
if (!Number.isInteger(body.duration) || Number(body.duration) < 4 || Number(body.duration) > 15) {
return fail("Invalid request: duration must be an integer from 4 to 15 seconds.");
}
if (typeof body.ratio !== "string" || !TEXT_TO_VIDEO_RATIOS.has(body.ratio)) {
return fail("Invalid request: text-to-video requires a supported non-adaptive ratio.");
}
if (
body.callback_url !== undefined &&
(typeof body.callback_url !== "string" || !isHttpUrl(body.callback_url))
) {
return fail("Invalid request: callback_url must be an HTTP or HTTPS URL.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- target implementation ---'
sed -n '1,180p' src/app/v1/_lib/proxy/video-generation-v2.ts
printf '%s\n' '--- related tests ---'
sed -n '1,180p' tests/unit/proxy/video-generation-v2.test.ts
printf '%s\n' '--- error and localization references ---'
rg -n --glob '*.{ts,tsx,json}' 'ProxyError|next-intl|Invalid request|error code|errorCode|validate\(' src tests | head -240
printf '%s\n' '--- v1 proxy structure ---'
fd -t f . src/app/v1 | sort | head -160

Repository: ding113/claude-code-hub

Length of output: 35867


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- validator call sites ---'
rg -n -C 8 'validateVideoGenerationV2TextRequest|VIDEO_GENERATION_V2_CREATE_PATH|video_generation' src/app/v1 tests | head -320
printf '%s\n' '--- proxy error definitions and handling ---'
sed -n '1,260p' src/app/v1/_lib/proxy/errors.ts
sed -n '1,280p' src/app/v1/_lib/proxy/error-handler.ts
sed -n '150,230p' src/app/v1/_lib/proxy-handler.ts
printf '%s\n' '--- route and response construction ---'
sed -n '1,260p' 'src/app/v1/[...route]/route.ts'
printf '%s\n' '--- API error localization flow ---'
rg -n -C 10 'api-error-i18n|errorCode.*detail|errorParams|request.validation_failed|messages.*error' src tests | head -320

Repository: ding113/claude-code-hub

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- validation throw and response path ---'
sed -n '3308,3355p' src/app/v1/_lib/proxy/forwarder.ts
rg -n -C 6 'buildError|clientErrorMessage|resolveFinalClientErrorMessage|getLocale' src/app/v1/_lib/proxy/error-handler.ts src/app/v1/_lib/proxy/responses.ts src/app/v1/_lib/proxy-handler.ts
printf '%s\n' '--- proxy response implementation ---'
rg -n 'class ProxyResponses|buildError|errorCode|detail|message' src/app/v1/_lib/proxy/responses.ts src/app/v1/_lib/proxy/errors.ts | head -180
sed -n '1,180p' src/app/v1/_lib/proxy/responses.ts
printf '%s\n' '--- locale use in v1 code ---'
rg -n -C 4 'getLocale|Accept-Language|accept-language|locale' src/app/v1 src/i18n | head -220
printf '%s\n' '--- translation message structure ---'
fd -t f . messages src | rg '(^|/)(en|zh-CN|zh-TW|ja|ru)(/|\\.|$)|messages|error-messages'
sed -n '1,240p' src/lib/utils/error-messages.ts

Repository: ding113/claude-code-hub

Length of output: 50381


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- proxy API error contract tests ---'
rg -n -C 8 'invalid_request|invalid_request_error|error\.message|ProxyResponses\.buildError|ProxyErrorHandler' tests/api tests/integration tests/unit/proxy | head -260
printf '%s\n' '--- existing proxy validation error patterns ---'
rg -n -C 3 'new ProxyError\(|return fail\(|Invalid request:' src/app/v1/_lib/proxy src/app/v1/_lib | head -280
printf '%s\n' '--- frontend API error translation boundary ---'
rg -n -C 8 'function getApiErrorMessageKey|class ApiError|getApiErrorMessageKey|errorCode' src/lib src/hooks src/components | head -220
printf '%s\n' '--- read-only call-graph invariant check ---'
python3 - <<'PY'
from pathlib import Path

validator = Path("src/app/v1/_lib/proxy/video-generation-v2.ts").read_text()
forwarder = Path("src/app/v1/_lib/proxy/forwarder.ts").read_text()
responses = Path("src/app/v1/_lib/proxy/responses.ts").read_text()

checks = {
    "validator returns message field": "ok: false; message: string" in validator,
    "forwarder throws ProxyError from validation message":
        "throw new ProxyError(videoValidation.message, 400);" in forwarder,
    "ProxyResponses serializes message":
        '"message": string' in responses and "message," in responses,
    "ProxyResponses derives code from status/type":
        "getErrorCode(status, finalType)" in responses,
    "ProxyResponses has no validation error-code argument":
        "buildError(\n    status: number,\n    message: string,\n    errorType?: string" in responses,
}
for name, result in checks.items():
    print(f"{name}: {result}")
PY

Repository: ding113/claude-code-hub

Length of output: 50379


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- existing localized proxy error precedent ---'
sed -n '1180,1220p' src/app/v1/_lib/proxy/session.ts
rg -n -C 5 'export (const|type).*ERROR_CODES|function getErrorMessageServer|getErrorMessageServer' src/lib/utils/error-messages.ts
printf '%s\n' '--- exact error response schema and tests ---'
python3 - <<'PY'
from pathlib import Path

forwarder = Path("src/app/v1/_lib/proxy/forwarder.ts").read_text()
handler = Path("src/app/v1/_lib/proxy/error-handler.ts").read_text()
responses = Path("src/app/v1/_lib/proxy/responses.ts").read_text()
validator = Path("src/app/v1/_lib/proxy/video-generation-v2.ts").read_text()

assert "throw new ProxyError(videoValidation.message, 400);" in forwarder
assert "clientErrorMessage = error.getClientSafeMessage();" in handler
assert "ProxyResponses.buildError(" in handler
assert "message," in responses
assert "getErrorCode(status, finalType)" in responses
assert "{ ok: false; message: string }" in validator
print("video validation -> ProxyError(message) -> client error message -> error.message: PASS")
print("response code is derived from HTTP status/type, not a validation-specific code: PASS")
print("validator currently exposes presentation text rather than a machine-readable validation code: PASS")
PY

Repository: ding113/claude-code-hub

Length of output: 2932


为视频生成验证错误使用 i18n 和稳定错误码。

验证错误会通过 ProxyError 写入 API 的 error.message。当前消息为硬编码英文,且 error.code 只能表示 HTTP 状态,不能标识具体验证失败。

  • src/app/v1/_lib/proxy/video-generation-v2.ts:53-89:返回稳定错误码,并在响应边界根据请求语言生成消息。
  • tests/unit/proxy/video-generation-v2.test.ts:25-39:断言错误码,不要断言英文消息片段。
📍 Affects 2 files
  • src/app/v1/_lib/proxy/video-generation-v2.ts#L53-L89 (this comment)
  • tests/unit/proxy/video-generation-v2.test.ts#L25-L39
🤖 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 `@src/app/v1/_lib/proxy/video-generation-v2.ts` around lines 53 - 89, Update
the validation returns in video-generation-v2.ts around the request checks to
use stable validation error codes instead of hardcoded English messages, while
generating localized messages at the response boundary based on the request
language. Update tests/unit/proxy/video-generation-v2.test.ts lines 25-39 to
assert the relevant error codes rather than English message fragments.

Source: Coding guidelines

@github-actions github-actions Bot added the size/M Medium PR (< 500 lines) label Aug 12, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7573e79e1d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +57 to +58
if (!Array.isArray(body.content) || body.content.length !== 1) {
return fail("Invalid request: text-to-video content must contain exactly one text item.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Check H3 content text before forwarding

For /v2/video_generation the user prompt is accepted in top-level content[].text, but the sensitive-word guard runs earlier in CHAT_PIPELINE and extractTextFromMessages only reads prompt, system, messages, and input. Any blocked term inside an H3 prompt therefore produces texts.length === 0 and is forwarded upstream; add extraction/normalization for this content shape before the guard decision.

Useful? React with 👍 / 👎.

Comment on lines +138 to +143
id: "video-generation-v2-create",
surface: "openai",
accountingTier: "none",
modelRequired: true,
rawPassthrough: false,
match: (pathname) => pathname === "/v2/video_generation",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Teach URL building about video_generation

Adding this /v2/video_generation family without updating buildProxyUrl's endpoint list means providers configured with the version-root base URL pattern that the helper supports elsewhere, e.g. https://api.minimax.io/v2, are called as https://api.minimax.io/v2/v2/video_generation because /video_generation does not match any endpoint regex and falls through to plain concatenation. Add the new video paths to targetEndpoints so version-root and endpoint-root provider URLs route correctly.

Useful? React with 👍 / 👎.

Comment on lines +53 to +54
if (body.model !== TEXT_TO_VIDEO_MODEL) {
return fail(`Invalid request: model must be ${TEXT_TO_VIDEO_MODEL}.`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Localize video validation failures

These new validation failures are returned to clients through ProxyError, but the messages are hardcoded English literals. The repository requires user-facing strings to use i18n across the supported languages, so invalid /v2/video_generation requests bypass the localized error catalog; route these messages through the existing i18n/error helper instead.

Useful? React with 👍 / 👎.

@github-actions github-actions 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.

Code Review Summary

The new video-generation routing, schema validation, and endpoint-family registration are well-structured and follow established patterns in the codebase (the v2 route mirrors v1beta, the endpoint-family overlap between create/resources matches the response-* families, and the validator is correctly placed after request transformations and before serialization). No code-level defects met the reporting threshold across all six review perspectives.

PR Size: M

  • Lines changed: 261 (258 additions / 3 deletions)
  • Files changed: 11

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 0 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Standards Note (Action Recommended)

Base branch targets main instead of dev. CLAUDE.md states under Repository Info:

PR Target Branch: dev (all pull requests must target the dev branch)

This PR should be re-targeted to dev before merge to comply with the repository's contribution policy.

Review Coverage

  • Logic and correctness - validator ordering, path matching via normalizeEndpointPath, endpoint-family overlap resolution
  • Security (OWASP Top 10) - callback_url validated as http(s) and forwarded only (not fetched server-side); no injection surface
  • Error handling - isHttpUrl catch surfaces as a 400 validation error; no silent/swallowed failures
  • Type safety - casts guarded by runtime validation; no any usage
  • Documentation accuracy - matcher comments in proxy.matcher.ts/proxy.ts correctly updated to include v2
  • Test coverage - happy path, 8 rejection cases, and non-create bypass covered
  • Code clarity - clean, readable, consistent with existing proxy families

Automated review by Claude AI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core area:provider enhancement New feature or request size/M Medium PR (< 500 lines)

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant