Dev open video - #4382
Conversation
自动同步上游
chore: 初始化 CI/CD 流水线与自动同步配置
- 新增 constant.ChannelTypeAIGCVideo 类型及其基础配置 - 在 endpoint_defaults.go 添加 OpenAIVideo 接口路径 - 更新 endpoint_type.go 支持 AIGCVideo 渠道类型映射 - 实现 relay/channel/task/aigc 下全新任务适配器及常量定义 - 在 relay_adaptor.go 添加 AIGCVideo 渠道任务适配器实例 - 增加 controller/channel-test.go 中 AIGCVideo 渠道的测试函数及流程 - 在 middleware/distributor.go 设置 AIGCVideo 特殊上下文参数 region - 在 model_ratio.go 新增 AIGC Video 系列模型的价格配置 - 在前端常量及编辑模态框中添加 AIGC Video 渠道选项及认证说明 - 更新前端渠道模型列表支持 AIGC Video 系列模型 - 新增 LOCAL_DEV_GUIDE.md,补充 Windows 本地开发环境启动指南文档 - 兼顾安全性采用 HMAC-SHA256 签名认证方式完成请求鉴权 - 实现任务查询接口,可获取视频生成任务的状态及结果URL
WalkthroughThis PR refactors CI/CD workflows (removes deprecated alpha, arm64, electron, and gitee-sync workflows; adds new prod-cd and test-ci pipelines), introduces comprehensive AIGC video channel support with task adaptor implementation, adds video model pricing entries, updates frontend channel configuration, and provides Windows local development documentation. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 12
🧹 Nitpick comments (3)
LOCAL_DEV_GUIDE.md (2)
224-230: Add language identifier to fenced code block.The code block showing the recommended development workflow should specify a language identifier (e.g.,
textorbash) for consistent rendering.📝 Suggested fix
-``` +```text 终端 1(后端): go run main.go 终端 2(前端): cd web && bun run dev 浏览器: http://localhost:5173🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@LOCAL_DEV_GUIDE.md` around lines 224 - 230, The fenced code block showing the dev workflow lacks a language identifier; update the triple-backtick fence that wraps the three-line snippet (the block containing "终端 1(后端): go run main.go", "终端 2(前端): cd web && bun run dev", and "浏览器: http://localhost:5173") to include a language tag such as text or bash (e.g., change ``` to ```text) so the block renders consistently.
33-41: Add language identifier to fenced code block.The code block showing the project structure should specify a language identifier (e.g.,
textorplaintext) for better rendering and accessibility.📝 Suggested fix
-``` +```text new-api/ ├── main.go # 后端入口 ├── web/ # React 前端(Vite + Semi Design)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@LOCAL_DEV_GUIDE.md` around lines 33 - 41, The fenced code block containing the project tree (starting with "new-api/" and the lines with "main.go", "web/", ".env.example", "go.mod", "web/package.json") is missing a language identifier; update the opening fence from ``` to include a plain-text identifier such as ```text or ```plaintext so the block renders/accessibility metadata correctly (e.g., change the opening fence immediately before "new-api/" to ```text).web/src/components/table/channels/modals/EditChannelModal.jsx (1)
653-662: Avoid maintaining another hard-coded AIGC model list.This list duplicates the backend AIGC
ModelListand pricing/docs model lists, so future additions can become selectable-but-unpriced or priced-but-unselectable. Prefer centralizing type 58 defaults ingetChannelModels(58)or returning them from the backend.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/table/channels/modals/EditChannelModal.jsx` around lines 653 - 662, The hard-coded AIGC Video model array in EditChannelModal.jsx duplicates backend model lists; replace the literal list in the case 58 branch with a call to the centralized source (e.g., use getChannelModels(58) or the backend-provided model list) so the UI consumes the single canonical model list; update imports/params to access getChannelModels (or call the existing API helper used elsewhere), set localModels = getChannelModels(58) (or assign the fetched backend result) and remove the inline array to avoid desynchronization with backend ModelList/pricing lists.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/prod-cd.yml:
- Around line 1-47: The workflow defined as "Build and Release Production"
contains a misplaced file that will not be executed; delete the redundant
inactive workflow file and merge its important build steps into the existing
prod-cd workflow: copy the build-job "build-prod-image" additions
(docker/setup-buildx-action@v3 step, the docker/build-push-action@v5 fields
platforms: linux/amd64,linux/arm64 and cache-from/cache-to settings, and any
meta step tags/labels usage) into the active prod-cd workflow so the multi-arch
build and GHA cache configuration are preserved, then remove the inactive file
to avoid duplication.
In @.github/test-ci.yml:
- Around line 1-37: The file containing the workflow named "Build for Test
Environment" with job "build-test-image" is a duplicate and inert (GitHub only
runs workflows placed in the workflows directory); delete this duplicate
workflow file (the one defining the "Build for Test Environment" workflow and
"build-test-image" job) from the repo so maintainers won't edit a non-running
copy, and verify the functional workflow remains in the active workflows
location.
In @.github/workflows/prod-cd.yml:
- Around line 1-47: There are two copies of the production CD workflow; keep the
one that actually runs (the workflow with name "Build Production Release" and
job "build-and-push-prod") and delete the duplicate file that lives outside the
workflows folder; before deleting, merge the missing multi-arch/buildx/cache
steps into this active workflow by adding the buildx setup and cache actions
into the "Build and push Production Docker image" stage (refer to step names
like "Log in to the Container registry", "Extract metadata for Docker", and the
build-push action) so the consolidated workflow includes multi-arch builds,
buildx setup, and caching, then remove the orphaned copy to leave a single
source of truth.
- Around line 4-7: The push tag trigger currently uses a loose glob 'v*' which
will match non-release tags; update the GitHub Actions trigger in the workflow
(the on: push: tags: entry) to use a SemVer-restricted pattern (e.g., 'v*.*.*'
or a full semver regex) to match only release tags and align with the sibling
workflow; modify the tags value in the .github/workflows/prod-cd.yml workflow's
on.push.tags from 'v*' to the tighter SemVer pattern so both workflows are
consistent.
- Around line 41-47: The workflow currently uses docker/build-push-action@v5 but
dropped multi-arch and build cache settings; add a prior step that runs
docker/setup-buildx-action@v3 to enable buildx, then update the
docker/build-push-action@v5 step (the step that uses tags: ${{
steps.meta.outputs.tags }} and labels: ${{ steps.meta.outputs.labels }}) to
include platforms: linux/amd64,linux/arm64 and cache settings (cache-from:
type=gha and cache-to: type=gha,mode=max) so builds are multi-arch and use
GitHub Actions cache; ensure the buildx setup step id is referenced if needed by
the build step.
In @.github/workflows/test-ci.yml:
- Around line 1-40: Remove the duplicate workflow file `.github/test-ci.yml` and
keep this workflow under `.github/workflows/`; delete the extraneous copy to
avoid confusion and stale drift. In the "Build and push Test Docker image" step
(docker/build-push-action@v5) update the tags configuration so you continue to
push the mutable :test tag but also push an immutable tag using the commit SHA
(e.g. add a second tag using ${{ github.sha }}), ensuring you reference the
existing "tags" key in that step rather than replacing it.
In `@controller/channel-test.go`:
- Around line 514-609: The testAIGCVideoChannel function returns testResult
values that set newAPIError but leave the result.context nil; update all returns
that include newAPIError (e.g., the "bad response status code" and "response
missing task id" return branches) to also set context: channel.Context (or the
channel's existing context field) so testAllChannels can safely read
result.context when handling enable/disable logic. Ensure any other branches
that construct newAPIError in testAIGCVideoChannel also populate the context
field with the channel's context.
In `@relay/channel/task/aigc/adaptor.go`:
- Around line 142-153: The billing size is currently read from req.Size (size :=
req.Size) but AIGC requests put resolution in metadata.output_config.resolution;
update the logic to prefer req.Metadata.OutputConfig.Resolution (or
Metadata.OutputConfig.Resolution) if present and non-empty, falling back to
req.Size, then compute ratios as before (use seconds variable and the ratios
map) and ensure the special-case checks for "1792x1024", "1024x1792", and
"1080P" also consider the metadata-based resolution value so 1080P submitted via
metadata is charged correctly.
- Around line 254-274: The request signing block in adaptor.go must fail fast
when the parsed `key` doesn't contain at least three pipe-delimited parts: in
the function that builds/signs the polling request (e.g., FetchTask), validate
the credential string before making the HTTP request and return an error if
`strings.Split(key, "|")` yields fewer than 3 parts; do not send an unsigned
request. Also prefer per-task credentials by using `task.PrivateData.Key` (when
present and non-empty) over `channel.Key` for async video follow-up polling and
ensure the caller supplies that per-task key into the signing logic so the
X-SubAppId/X-SecretId/X-Timestamp/X-Signature headers are only set when a valid
key is provided.
In `@国产视频模型文档-AIGC/任务查询.txt`:
- Around line 26-32: The OpenAPI snippet only documents Authorization but the
implementation uses HMAC headers; update the spec to add header parameters for
X-SubAppId, X-SecretId, X-Timestamp, X-Signature (required string headers) and
X-Region (optional string) alongside or instead of the bearer Authorization
entry so consumers can reproduce the auth flow; for each header (X-SubAppId,
X-SecretId, X-Timestamp, X-Signature, X-Region) add description, in: header,
type: string, and example values and mark X-Region optional while the others are
required.
In `@国产视频模型文档-AIGC/视频接口.txt`:
- Around line 47-65: The example payload is missing the required aspect_ratio
under metadata.output_config; update the example so metadata.output_config
includes both required fields resolution and aspect_ratio (and any other
required nested fields), and verify the top-level required keys model, prompt,
and metadata are present; ensure the example mirrors the schema structure
exactly (e.g., metadata.output_config.resolution and
metadata.output_config.aspect_ratio) so generated clients and contract tests
accept it—apply the same fix to the other example instances referenced around
the same block.
- Around line 20-26: The spec currently documents only an Authorization header
(the "Authorization" header block) but the implementation uses HMAC-style
headers; update the OpenAPI header definitions to replace or supplement the
Authorization bearer example with explicit headers: X-SubAppId, X-SecretId,
X-Timestamp, X-Signature, and optional X-Region (each as required/optional with
type: string and an example value), and similarly update the other duplicated
header blocks referenced (around the section noted 128-139) so consumers can
construct the HMAC signing headers correctly when testing the channel.
---
Nitpick comments:
In `@LOCAL_DEV_GUIDE.md`:
- Around line 224-230: The fenced code block showing the dev workflow lacks a
language identifier; update the triple-backtick fence that wraps the three-line
snippet (the block containing "终端 1(后端): go run main.go", "终端 2(前端): cd web &&
bun run dev", and "浏览器: http://localhost:5173") to include a language
tag such as text or bash (e.g., change ``` to ```text) so the block renders
consistently.
- Around line 33-41: The fenced code block containing the project tree (starting
with "new-api/" and the lines with "main.go", "web/", ".env.example", "go.mod",
"web/package.json") is missing a language identifier; update the opening fence
from ``` to include a plain-text identifier such as ```text or ```plaintext so
the block renders/accessibility metadata correctly (e.g., change the opening
fence immediately before "new-api/" to ```text).
In `@web/src/components/table/channels/modals/EditChannelModal.jsx`:
- Around line 653-662: The hard-coded AIGC Video model array in
EditChannelModal.jsx duplicates backend model lists; replace the literal list in
the case 58 branch with a call to the centralized source (e.g., use
getChannelModels(58) or the backend-provided model list) so the UI consumes the
single canonical model list; update imports/params to access getChannelModels
(or call the existing API helper used elsewhere), set localModels =
getChannelModels(58) (or assign the fetched backend result) and remove the
inline array to avoid desynchronization with backend ModelList/pricing lists.
🪄 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
Run ID: 82479e7f-8b05-455b-a53a-a24218176ab3
⛔ Files ignored due to path filters (1)
web/bun.lockis excluded by!**/*.lock
📒 Files selected for processing (24)
.github/prod-cd.yml.github/test-ci.yml.github/workflows/docker-image-alpha.yml.github/workflows/docker-image-arm64.yml.github/workflows/electron-build.yml.github/workflows/prod-cd.yml.github/workflows/sync-to-gitee.yml.github/workflows/test-ci.ymlLOCAL_DEV_GUIDE.mdcommon/endpoint_defaults.gocommon/endpoint_type.goconstant/channel.gocontroller/channel-test.gomiddleware/distributor.gorelay/channel/task/aigc/adaptor.gorelay/channel/task/aigc/constants.gorelay/relay_adaptor.goreview_diff.txtsetting/ratio_setting/model_ratio.goweb/src/components/table/channels/modals/EditChannelModal.jsxweb/src/constants/channel.constants.js国产视频模型文档-AIGC/任务查询.txt国产视频模型文档-AIGC/国产视频模型全系列文档.txt国产视频模型文档-AIGC/视频接口.txt
💤 Files with no reviewable changes (4)
- .github/workflows/electron-build.yml
- .github/workflows/sync-to-gitee.yml
- .github/workflows/docker-image-arm64.yml
- .github/workflows/docker-image-alpha.yml
| name: Build and Release Production | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*.*.*' | ||
|
|
||
| env: | ||
| REGISTRY: ghcr.io | ||
| IMAGE_NAME: ${{ github.repository }} | ||
|
|
||
| jobs: | ||
| build-prod-image: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| permissions: | ||
| contents: read | ||
| packages: write | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: docker/login-action@v3 | ||
| with: | ||
| registry: ${{ env.REGISTRY }} | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - id: meta | ||
| uses: docker/metadata-action@v5 | ||
| with: | ||
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | ||
| tags: | | ||
| type=semver,pattern={{version}} | ||
| type=raw,value=latest | ||
|
|
||
| - uses: docker/setup-buildx-action@v3 | ||
|
|
||
| - uses: docker/build-push-action@v5 | ||
| with: | ||
| context: . | ||
| push: true | ||
| platforms: linux/amd64,linux/arm64 | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} | ||
| cache-from: type=gha | ||
| cache-to: type=gha,mode=max |
There was a problem hiding this comment.
This file is in the wrong location and will never run.
GitHub Actions only discovers workflows under .github/workflows/. A file at .github/prod-cd.yml is inert — it will not trigger on tag pushes despite the on: push: tags block. Given .github/workflows/prod-cd.yml already exists in this PR, please delete this file and instead merge its extra steps (buildx setup, platforms: linux/amd64,linux/arm64, gha cache) into .github/workflows/prod-cd.yml, otherwise the multi-arch and caching configuration that appears to be the whole point of this file is silently lost.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/prod-cd.yml around lines 1 - 47, The workflow defined as "Build and
Release Production" contains a misplaced file that will not be executed; delete
the redundant inactive workflow file and merge its important build steps into
the existing prod-cd workflow: copy the build-job "build-prod-image" additions
(docker/setup-buildx-action@v3 step, the docker/build-push-action@v5 fields
platforms: linux/amd64,linux/arm64 and cache-from/cache-to settings, and any
meta step tags/labels usage) into the active prod-cd workflow so the multi-arch
build and GHA cache configuration are preserved, then remove the inactive file
to avoid duplication.
| # .github/workflows/test-ci.yml | ||
| name: Build for Test Environment | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - prod # 只监听 prod 分支的变更 | ||
|
|
||
| env: | ||
| REGISTRY: ghcr.io | ||
| IMAGE_NAME: ${{ github.repository }} | ||
|
|
||
| jobs: | ||
| build-test-image: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Log in to the Container registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ${{ env.REGISTRY }} | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Build and push Test Docker image | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| context: . | ||
| push: true | ||
| # 固定打上 test 标签,供测试服务器拉取 | ||
| tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test |
There was a problem hiding this comment.
This file is in the wrong location and will never run.
Same issue as .github/prod-cd.yml: GitHub Actions only picks up workflow YAML under .github/workflows/. This file at .github/test-ci.yml is a no-op. The functionally identical .github/workflows/test-ci.yml already covers this trigger, so please delete this duplicate to prevent future maintainers from editing the inert copy.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/test-ci.yml around lines 1 - 37, The file containing the workflow
named "Build for Test Environment" with job "build-test-image" is a duplicate
and inert (GitHub only runs workflows placed in the workflows directory); delete
this duplicate workflow file (the one defining the "Build for Test Environment"
workflow and "build-test-image" job) from the repo so maintainers won't edit a
non-running copy, and verify the functional workflow remains in the active
workflows location.
| name: Build Production Release | ||
|
|
||
| # 触发条件:当推送以 'v' 开头的 tag 时触发 | ||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' | ||
|
|
||
| env: | ||
| REGISTRY: ghcr.io | ||
| IMAGE_NAME: ${{ github.repository }} | ||
|
|
||
| jobs: | ||
| build-and-push-prod: | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Log in to the Container registry | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ${{ env.REGISTRY }} | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Extract metadata for Docker | ||
| id: meta | ||
| uses: docker/metadata-action@v5 | ||
| with: | ||
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | ||
| # 自动提取你打的 Tag 版本号,并附加一个 latest 标签 | ||
| tags: | | ||
| type=semver,pattern={{version}} | ||
| type=raw,value=latest | ||
|
|
||
| - name: Build and push Production Docker image | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| context: . | ||
| push: true | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Duplicate of .github/prod-cd.yml — consolidate into this single file.
.github/prod-cd.yml sits outside .github/workflows/ so GitHub Actions will not run it; this copy is the one that actually executes. Please delete .github/prod-cd.yml after folding the missing multi-arch/buildx/cache steps (see the other comment) into this file, so there is one source of truth.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/prod-cd.yml around lines 1 - 47, There are two copies of
the production CD workflow; keep the one that actually runs (the workflow with
name "Build Production Release" and job "build-and-push-prod") and delete the
duplicate file that lives outside the workflows folder; before deleting, merge
the missing multi-arch/buildx/cache steps into this active workflow by adding
the buildx setup and cache actions into the "Build and push Production Docker
image" stage (refer to step names like "Log in to the Container registry",
"Extract metadata for Docker", and the build-push action) so the consolidated
workflow includes multi-arch builds, buildx setup, and caching, then remove the
orphaned copy to leave a single source of truth.
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' |
There was a problem hiding this comment.
Tag filter inconsistency with the sibling file.
This workflow triggers on v* while .github/prod-cd.yml (the duplicate) triggers on v*.*.*. v* will also match non-release tags such as v1-rc, vtest, etc., which can accidentally cut a production release and publish :latest. Tighten to SemVer to match intent:
tags:
- - 'v*'
+ - 'v*.*.*'📝 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.
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/prod-cd.yml around lines 4 - 7, The push tag trigger
currently uses a loose glob 'v*' which will match non-release tags; update the
GitHub Actions trigger in the workflow (the on: push: tags: entry) to use a
SemVer-restricted pattern (e.g., 'v*.*.*' or a full semver regex) to match only
release tags and align with the sibling workflow; modify the tags value in the
.github/workflows/prod-cd.yml workflow's on.push.tags from 'v*' to the tighter
SemVer pattern so both workflows are consistent.
| - name: Build and push Production Docker image | ||
| uses: docker/build-push-action@v5 | ||
| with: | ||
| context: . | ||
| push: true | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} |
There was a problem hiding this comment.
Regression: multi-arch (arm64) builds and build cache were dropped.
Comparing with the near-duplicate .github/prod-cd.yml and the removed docker-image-arm64.yml workflow mentioned in the PR summary, this workflow is missing:
docker/setup-buildx-action@v3(required for multi-platform builds)platforms: linux/amd64,linux/arm64cache-from: type=gha/cache-to: type=gha,mode=max
As written, production releases will publish amd64 only, silently breaking arm64 consumers that the previous workflows supported. Please restore these:
🔧 Proposed fix
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
- name: Build and push Production Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
+ platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max📝 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.
| - name: Build and push Production Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Build and push Production Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| platforms: linux/amd64,linux/arm64 | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/prod-cd.yml around lines 41 - 47, The workflow currently
uses docker/build-push-action@v5 but dropped multi-arch and build cache
settings; add a prior step that runs docker/setup-buildx-action@v3 to enable
buildx, then update the docker/build-push-action@v5 step (the step that uses
tags: ${{ steps.meta.outputs.tags }} and labels: ${{ steps.meta.outputs.labels
}}) to include platforms: linux/amd64,linux/arm64 and cache settings
(cache-from: type=gha and cache-to: type=gha,mode=max) so builds are multi-arch
and use GitHub Actions cache; ensure the buildx setup step id is referenced if
needed by the build step.
| size := req.Size | ||
| if size == "" { | ||
| size = "720x1280" | ||
| } | ||
|
|
||
| ratios := map[string]float64{ | ||
| "seconds": float64(seconds), | ||
| "size": 1, | ||
| } | ||
| if size == "1792x1024" || size == "1024x1792" || size == "1080P" { | ||
| ratios["size"] = 1.666667 | ||
| } |
There was a problem hiding this comment.
Use metadata.output_config.resolution for billing size.
AIGC requests document and send resolution under metadata.output_config.resolution, but billing only checks top-level size; 1080P requests submitted through the documented shape will be charged with size = 1.
💰 Suggested billing fix
size := req.Size
+ if size == "" && req.Metadata != nil {
+ if outputConfig, ok := req.Metadata["output_config"].(map[string]interface{}); ok {
+ if resolution, ok := outputConfig["resolution"].(string); ok {
+ size = strings.TrimSpace(resolution)
+ }
+ }
+ }
if size == "" {
size = "720x1280"
}
@@
- if size == "1792x1024" || size == "1024x1792" || size == "1080P" {
+ normalizedSize := strings.ToUpper(size)
+ if normalizedSize == "1792X1024" || normalizedSize == "1024X1792" || normalizedSize == "1080P" {
ratios["size"] = 1.666667
}📝 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.
| size := req.Size | |
| if size == "" { | |
| size = "720x1280" | |
| } | |
| ratios := map[string]float64{ | |
| "seconds": float64(seconds), | |
| "size": 1, | |
| } | |
| if size == "1792x1024" || size == "1024x1792" || size == "1080P" { | |
| ratios["size"] = 1.666667 | |
| } | |
| size := req.Size | |
| if size == "" && req.Metadata != nil { | |
| if outputConfig, ok := req.Metadata["output_config"].(map[string]interface{}); ok { | |
| if resolution, ok := outputConfig["resolution"].(string); ok { | |
| size = strings.TrimSpace(resolution) | |
| } | |
| } | |
| } | |
| if size == "" { | |
| size = "720x1280" | |
| } | |
| ratios := map[string]float64{ | |
| "seconds": float64(seconds), | |
| "size": 1, | |
| } | |
| normalizedSize := strings.ToUpper(size) | |
| if normalizedSize == "1792X1024" || normalizedSize == "1024X1792" || normalizedSize == "1080P" { | |
| ratios["size"] = 1.666667 | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@relay/channel/task/aigc/adaptor.go` around lines 142 - 153, The billing size
is currently read from req.Size (size := req.Size) but AIGC requests put
resolution in metadata.output_config.resolution; update the logic to prefer
req.Metadata.OutputConfig.Resolution (or Metadata.OutputConfig.Resolution) if
present and non-empty, falling back to req.Size, then compute ratios as before
(use seconds variable and the ratios map) and ensure the special-case checks for
"1792x1024", "1024x1792", and "1080P" also consider the metadata-based
resolution value so 1080P submitted via metadata is charged correctly.
| // Parse pipe-separated key and set auth headers | ||
| parts := strings.Split(key, "|") | ||
| if len(parts) >= 3 { | ||
| subAppId := parts[0] | ||
| secretId := parts[1] | ||
| secretKey := parts[2] | ||
|
|
||
| timestamp := strconv.FormatInt(time.Now().Unix(), 10) | ||
| signStr := fmt.Sprintf("%s\n%s\n%s", secretId, timestamp, secretKey) | ||
| h := hmac.New(sha256.New, []byte(secretKey)) | ||
| h.Write([]byte(signStr)) | ||
| signature := hex.EncodeToString(h.Sum(nil)) | ||
|
|
||
| req.Header.Set("X-SubAppId", subAppId) | ||
| req.Header.Set("X-SecretId", secretId) | ||
| req.Header.Set("X-Timestamp", timestamp) | ||
| req.Header.Set("X-Signature", signature) | ||
| if len(parts) >= 4 && parts[3] != "" { | ||
| req.Header.Set("X-Region", parts[3]) | ||
| } | ||
| } |
There was a problem hiding this comment.
Fail fast when polling credentials are malformed.
If key has fewer than three pipe-delimited parts, FetchTask still sends an unsigned request and turns a local configuration/auth-context problem into an upstream polling failure. Return an error before issuing the request, and make sure the caller passes the captured per-task key when available. Based on learnings, task.PrivateData.Key may hold a per-task key that should be preferred over channel.Key for async video follow-up requests.
🔐 Suggested validation
// Parse pipe-separated key and set auth headers
parts := strings.Split(key, "|")
- if len(parts) >= 3 {
- subAppId := parts[0]
- secretId := parts[1]
- secretKey := parts[2]
+ if len(parts) < 3 || strings.TrimSpace(parts[0]) == "" || strings.TrimSpace(parts[1]) == "" || strings.TrimSpace(parts[2]) == "" {
+ return nil, fmt.Errorf("invalid AIGC key format, expected SubAppId|SecretId|SecretKey[|Region]")
+ }
+ subAppId := parts[0]
+ secretId := parts[1]
+ secretKey := parts[2]
- timestamp := strconv.FormatInt(time.Now().Unix(), 10)
- signStr := fmt.Sprintf("%s\n%s\n%s", secretId, timestamp, secretKey)
- h := hmac.New(sha256.New, []byte(secretKey))
- h.Write([]byte(signStr))
- signature := hex.EncodeToString(h.Sum(nil))
+ timestamp := strconv.FormatInt(time.Now().Unix(), 10)
+ signStr := fmt.Sprintf("%s\n%s\n%s", secretId, timestamp, secretKey)
+ h := hmac.New(sha256.New, []byte(secretKey))
+ h.Write([]byte(signStr))
+ signature := hex.EncodeToString(h.Sum(nil))
- req.Header.Set("X-SubAppId", subAppId)
- req.Header.Set("X-SecretId", secretId)
- req.Header.Set("X-Timestamp", timestamp)
- req.Header.Set("X-Signature", signature)
- if len(parts) >= 4 && parts[3] != "" {
- req.Header.Set("X-Region", parts[3])
- }
+ req.Header.Set("X-SubAppId", subAppId)
+ req.Header.Set("X-SecretId", secretId)
+ req.Header.Set("X-Timestamp", timestamp)
+ req.Header.Set("X-Signature", signature)
+ if len(parts) >= 4 && parts[3] != "" {
+ req.Header.Set("X-Region", parts[3])
}📝 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.
| // Parse pipe-separated key and set auth headers | |
| parts := strings.Split(key, "|") | |
| if len(parts) >= 3 { | |
| subAppId := parts[0] | |
| secretId := parts[1] | |
| secretKey := parts[2] | |
| timestamp := strconv.FormatInt(time.Now().Unix(), 10) | |
| signStr := fmt.Sprintf("%s\n%s\n%s", secretId, timestamp, secretKey) | |
| h := hmac.New(sha256.New, []byte(secretKey)) | |
| h.Write([]byte(signStr)) | |
| signature := hex.EncodeToString(h.Sum(nil)) | |
| req.Header.Set("X-SubAppId", subAppId) | |
| req.Header.Set("X-SecretId", secretId) | |
| req.Header.Set("X-Timestamp", timestamp) | |
| req.Header.Set("X-Signature", signature) | |
| if len(parts) >= 4 && parts[3] != "" { | |
| req.Header.Set("X-Region", parts[3]) | |
| } | |
| } | |
| // Parse pipe-separated key and set auth headers | |
| parts := strings.Split(key, "|") | |
| if len(parts) < 3 || strings.TrimSpace(parts[0]) == "" || strings.TrimSpace(parts[1]) == "" || strings.TrimSpace(parts[2]) == "" { | |
| return nil, fmt.Errorf("invalid AIGC key format, expected SubAppId|SecretId|SecretKey[|Region]") | |
| } | |
| subAppId := parts[0] | |
| secretId := parts[1] | |
| secretKey := parts[2] | |
| timestamp := strconv.FormatInt(time.Now().Unix(), 10) | |
| signStr := fmt.Sprintf("%s\n%s\n%s", secretId, timestamp, secretKey) | |
| h := hmac.New(sha256.New, []byte(secretKey)) | |
| h.Write([]byte(signStr)) | |
| signature := hex.EncodeToString(h.Sum(nil)) | |
| req.Header.Set("X-SubAppId", subAppId) | |
| req.Header.Set("X-SecretId", secretId) | |
| req.Header.Set("X-Timestamp", timestamp) | |
| req.Header.Set("X-Signature", signature) | |
| if len(parts) >= 4 && parts[3] != "" { | |
| req.Header.Set("X-Region", parts[3]) | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@relay/channel/task/aigc/adaptor.go` around lines 254 - 274, The request
signing block in adaptor.go must fail fast when the parsed `key` doesn't contain
at least three pipe-delimited parts: in the function that builds/signs the
polling request (e.g., FetchTask), validate the credential string before making
the HTTP request and return an error if `strings.Split(key, "|")` yields fewer
than 3 parts; do not send an unsigned request. Also prefer per-task credentials
by using `task.PrivateData.Key` (when present and non-empty) over `channel.Key`
for async video follow-up polling and ensure the caller supplies that per-task
key into the signing logic so the X-SubAppId/X-SecretId/X-Timestamp/X-Signature
headers are only set when a valid key is provided.
| - name: Authorization | ||
| in: header | ||
| description: '' | ||
| example: '{{Authorization}}' | ||
| schema: | ||
| type: string | ||
| default: '{{Authorization}}' |
There was a problem hiding this comment.
Document the HMAC headers used by the implementation.
The AIGC adaptor signs task-query requests with X-SubAppId, X-SecretId, X-Timestamp, X-Signature, and optional X-Region, but this spec only documents a bearer Authorization header. Consumers following this doc will not be able to reproduce the implemented auth flow.
📝 Suggested doc adjustment
- - name: Authorization
+ - name: X-SubAppId
in: header
- description: ''
- example: '{{Authorization}}'
+ description: AIGC sub application id
schema:
type: string
- default: '{{Authorization}}'
+ - name: X-SecretId
+ in: header
+ description: AIGC secret id
+ schema:
+ type: string
+ - name: X-Timestamp
+ in: header
+ description: Unix timestamp used in the signature string
+ schema:
+ type: string
+ - name: X-Signature
+ in: header
+ description: HMAC-SHA256 signature
+ schema:
+ type: string
+ - name: X-Region
+ in: header
+ required: false
+ description: Optional AIGC region
+ schema:
+ type: stringAlso applies to: 117-128
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@国产视频模型文档-AIGC/任务查询.txt` around lines 26 - 32, The OpenAPI snippet only
documents Authorization but the implementation uses HMAC headers; update the
spec to add header parameters for X-SubAppId, X-SecretId, X-Timestamp,
X-Signature (required string headers) and X-Region (optional string) alongside
or instead of the bearer Authorization entry so consumers can reproduce the auth
flow; for each header (X-SubAppId, X-SecretId, X-Timestamp, X-Signature,
X-Region) add description, in: header, type: string, and example values and mark
X-Region optional while the others are required.
| - name: Authorization | ||
| in: header | ||
| description: '' | ||
| required: false | ||
| example: Bearer {{key}} | ||
| schema: | ||
| type: string |
There was a problem hiding this comment.
Document the actual AIGC signing headers instead of bearer auth only.
The implementation sends HMAC authentication headers, not just Authorization: Bearer .... This spec should list X-SubAppId, X-SecretId, X-Timestamp, X-Signature, and optional X-Region so operators can configure and test the channel correctly.
Also applies to: 128-139
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@国产视频模型文档-AIGC/视频接口.txt` around lines 20 - 26, The spec currently documents
only an Authorization header (the "Authorization" header block) but the
implementation uses HMAC-style headers; update the OpenAPI header definitions to
replace or supplement the Authorization bearer example with explicit headers:
X-SubAppId, X-SecretId, X-Timestamp, X-Signature, and optional X-Region (each as
required/optional with type: string and an example value), and similarly update
the other duplicated header blocks referenced (around the section noted 128-139)
so consumers can construct the HMAC signing headers correctly when testing the
channel.
| required: | ||
| - resolution | ||
| - aspect_ratio | ||
| x-apifox-orders: | ||
| - resolution | ||
| - aspect_ratio | ||
| required: | ||
| - output_config | ||
| x-apifox-orders: | ||
| - output_config | ||
| required: | ||
| - model | ||
| - prompt | ||
| - metadata | ||
| x-apifox-orders: | ||
| - model | ||
| - prompt | ||
| - metadata | ||
| example: |
There was a problem hiding this comment.
Make the example satisfy the declared required schema.
aspect_ratio is required by the schema, but the example omits it under metadata.output_config, so generated clients or contract tests will reject the sample payload.
📝 Suggested example fix
output_config:
resolution: 1080P
+ aspect_ratio: '16:9'
audio_generation: EnabledAlso applies to: 75-78
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@国产视频模型文档-AIGC/视频接口.txt` around lines 47 - 65, The example payload is missing
the required aspect_ratio under metadata.output_config; update the example so
metadata.output_config includes both required fields resolution and aspect_ratio
(and any other required nested fields), and verify the top-level required keys
model, prompt, and metadata are present; ensure the example mirrors the schema
structure exactly (e.g., metadata.output_config.resolution and
metadata.output_config.aspect_ratio) so generated clients and contract tests
accept it—apply the same fix to the other example instances referenced around
the same block.
Important
📝 变更描述 / Description
(简述:做了什么?为什么这样改能生效?请基于你对代码逻辑的理解来写,避免粘贴未经整理的内容)
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
Summary by CodeRabbit
New Features
Documentation
Chores