Compare commits

..

32 Commits

Author SHA1 Message Date
xiaoxia 58d78c3184 Merge pull request 'feat(ditto): 支持后台配置豆包API Key + 修复单句兜底bug' (#2268) from fix/ditto-apikey-config into develop
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m51s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m29s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m3s
CI/CD Pipeline / Build Staging API Image (push) Successful in 4m9s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 4m17s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 6m12s
AI Code Review / AI Code Review (pull_request) Successful in 6m38s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 7m12s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 9m13s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 8m7s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m28s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m41s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m16s
CI/CD Pipeline / Integration Tests (push) Successful in 30m3s
CI/CD Pipeline / Validate - Style (push) Successful in 31m48s
CI/CD Pipeline / Unit Tests (push) Successful in 39m12s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 40m14s
CI/CD Pipeline / Validate - Security (push) Successful in 1h43m4s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-11 20:30:54 +08:00
xiaoxia 0c1dbfc5a7 Merge pull request 'fix(viral-video): worker侧OSS签名URL重签2h,修复Wan/Seedance下载过期URL失败' (#2270) from fix/viral-video-step-error-isolation into develop
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m50s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m14s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m47s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 38s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 23s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m1s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 12s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m48s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 6m3s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 5m19s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m7s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m30s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m15s
CI/CD Pipeline / Validate - Style (push) Successful in 25m4s
CI/CD Pipeline / Integration Tests (push) Successful in 22m37s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 27m4s
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
2026-10-11 19:57:10 +08:00
CI Bot 312210c3d5 fix(viral-video): OSS签名URL过期导致Wan/Seedance下载失败——worker侧重签2h
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 25s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 46s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m40s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m40s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m38s
AI Code Review / AI Code Review (pull_request) Successful in 6m58s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 38s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 24m45s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 24m26s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 25m6s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 30m14s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 1h17m37s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 1s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
根因:用户上传图片时签的OSS URL默认expires=3600s(1h),在文案页停留超过1小时后点生成视频,
URL已过期,Wan/Seedance首帧下载报 Failed to download。

修复:
1. 新增_refresh_oss_signed_url() helper:识别我们OSS域名的URL(bucket.oss-cn-*.aliyuncs.com),
   通过get_download_url重签2h;外链原样返回;storage_key签公网URL
2. _normalize_image_url重写:对http(s) URL不再原样透传,统一走helper重签
3. _step_video_analysis:参考视频URL重签
4. _run_render_pipeline阶段3入口:images和ref_videos全部重签(双保险,_normalize已做一次)

不影响:信任链预热daemon用的storage_key不受影响;外链图片/Ark t2i产物原样透传
2026-10-11 19:55:48 +08:00
xiaoxia 70a26b053a ci: trigger staging deploy (viral-video error isolation 36c30e5)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (push) Successful in 3s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m5s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 1m18s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 51s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 2m14s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m38s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 6m19s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
AI Code Review / AI Code Review (pull_request) Successful in 8m2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 9m14s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 9m45s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 3m25s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m44s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m2s
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
2026-10-11 19:39:29 +08:00
xiaoxia bec75a075b Merge pull request 'fix(viral-video): 新一轮任务清空上一轮错误残留+错误阶段关键词兜底归因' (#2269) from fix/viral-video-step-error-isolation into develop
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 9s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 15s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m12s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m50s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m22s
AI Code Review / AI Code Review (pull_request) Successful in 9m19s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m43s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m54s
CI/CD Pipeline / Build Staging API Image (push) Successful in 5m1s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 4m13s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
2026-10-11 19:16:57 +08:00
自动化测试Agent 222c41bd55 test(ditto): 补充API Key配置/脱敏/client重建/单句兜底单测
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 42s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 6m11s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 7m14s
AI Code Review / AI Code Review (pull_request) Successful in 7m56s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 16m46s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 17m33s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m51s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 18m56s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 22m41s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 1h9m54s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 55s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m11s
- 路由层:_validate_value 密钥校验、白名单包含 doubao_api_key、
  GET 脱敏(DB配置/env配置/未配置/不明文泄露)、PUT 响应脱敏
- service 层:_get_llm_client 用 DB key/key变化重建/key不变复用/
  空key走默认、单句文案中性兜底(>=1)
2026-10-11 19:14:23 +08:00
CI Bot 36c30e5b6f fix(viral-video): 修复新一轮任务开始时上一轮错误残留显示+错误阶段关键词兜底归因
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m53s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 41s
CI/CD Pipeline / PR Build API Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m6s
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m49s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 15s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m36s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 44s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 7m59s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 16m3s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 20m12s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 1h8m6s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
- handleAnalyzeImages开始新分析时清空analysisError/copyError/videoError/imageAnalysis/storyboard
- handleGenerateCopy/handleGenerateVideo进入对应阶段时清空其他阶段错误
- handleRetry重试时清空旧imageAnalysis/storyboard产物
- onPollUpdate failed分支+activeError派生加关键词兜底(Wan/Seedance/VLM/OCR等),防止current_stage丢失时错误归到文案
- 解决BUG:用户只上传图片没点生成文案时,STEP3区域显示上一次的「视频生成失败:Wan 3.0…」
2026-10-11 19:04:26 +08:00
自动化测试Agent eceb454111 feat(ditto): 支持后台配置豆包API Key + 修复单句兜底bug
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m30s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m51s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 5m29s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 5m50s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m19s
AI Code Review / AI Code Review (pull_request) Successful in 6m56s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 11m14s
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
- admin/ditto_emotion 白名单新增 doubao_api_key(STRING)
- GET /config 对密钥脱敏:已配置返回 ***已配置***,不暴露明文和 env 默认值
- PUT 响应中密钥值同样脱敏
- DittoEmotionService._get_llm_client 优先读 DB 配置 doubao_api_key,
  key 变化时自动重建 client;DB/env 均未配置时降级关键词匹配
- 修复 _cached_analyze 单句兜底:len(pre_splits) > 1 → >= 1,
  单句文案也走中性兜底而非直接返回空
2026-10-11 19:02:23 +08:00
xiaoxia c8c9c8b35e Merge pull request 'fix(ditto): 修复 _verify_internal_api_key 返回 bool 时 updated_by 切片 TypeError' (#2267) from fix/ditto-emotion-updated-by-bool into develop
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m5s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m30s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m20s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m55s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Successful in 18s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m21s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m30s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m34s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m29s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m38s
CI/CD Pipeline / Validate - Style (push) Successful in 6m0s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m18s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m18s
AI Code Review / AI Code Review (pull_request) Successful in 7m25s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m31s
CI/CD Pipeline / Integration Tests (push) Successful in 7m53s
CI/CD Pipeline / Unit Tests (push) Successful in 13m29s
CI/CD Pipeline / Validate - Security (push) Successful in 18m56s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-11 08:19:13 +08:00
CI Bot e458ffeb57 fix(ditto): 修复 _verify_internal_api_key 返回 bool 时 updated_by 切片报错
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m27s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m55s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m15s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m10s
AI Code Review / AI Code Review (pull_request) Successful in 7m5s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 7m6s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 7m17s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 8m1s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m0s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m45s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 26m42s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 38s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m27s
_verify_internal_api_key 在 staging 环境(无 INTERNAL_API_KEYS 配置 + 非 production)
返回 True(bool)而非 API key 字符串,x_api_key[:8] 会报 TypeError:
'bool' object is not subscriptable。
改为 str(x_api_key)[:8] + 对 True 的特殊判断。
2026-10-11 07:49:34 +08:00
CI Bot 02866a64dd style: auto-format with black + isort + ruff + prettier [skip ci-format-check]
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 5s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 10s
CI/CD Pipeline / Check push changed paths (push) Successful in 10s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 59s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m14s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 15s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 39s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m48s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m55s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m44s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m21s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m25s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m43s
CI/CD Pipeline / Integration Tests (push) Successful in 6m8s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 7m4s
CI/CD Pipeline / Validate - Style (push) Successful in 7m16s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m26s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m30s
AI Code Review / AI Code Review (pull_request) Successful in 6m29s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Failing after 13m39s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (push) Successful in 14m25s
CI/CD Pipeline / Validate - Security (push) Successful in 20m53s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m24s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 10m2s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 10m15s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 17m5s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 27m48s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
2026-10-10 23:02:12 +00:00
Agent 4248ea2a59 Merge pull request #2266: fix(viral-video): 补回 PR#2256 丢失的多角色核心代码
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 9s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m1s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m38s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 54s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m3s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m9s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m32s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m59s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m41s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m32s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m45s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Failing after 12m53s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m38s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m44s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m57s
CI/CD Pipeline / Integration Tests (push) Successful in 7m48s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 8m51s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
2026-10-11 06:38:06 +08:00
Agent 4e5d365277 fix(viral-video): 补回 PR#2256 丢失的多角色核心代码
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 54s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m14s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 4m54s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 5m0s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 5m33s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 6m34s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 6m45s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 7m28s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 7m36s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 7m46s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 15m52s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 11m17s
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
- _marketing_purpose_hint: 20 种营销目的提示
- _target_customer_hint: 目标客户台词风格指导
- _parse_speaker_segments: 解析 [speaker:xxx] 标记
- _get_speaker_voice_id: 主角/配角音色分配
- 前端 speaker 标签渲染 (vv-sb-speaker-tag)
- 短剧模式提示条
2026-10-11 06:37:26 +08:00
Agent 22b9019325 Merge pull request #2264: fix(ci): mypy pip fallback + pin version
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (push) Successful in 5s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m5s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m37s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m35s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m45s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m3s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m13s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m49s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m21s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 5m22s
CI/CD Pipeline / CI Gate (pull_request) Successful in 12s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m16s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m31s
AI Code Review / AI Code Review (pull_request) Successful in 7m15s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m12s
CI/CD Pipeline / Integration Tests (push) Successful in 11m39s
CI/CD Pipeline / Validate - Style (push) Successful in 12m23s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 15m5s
CI/CD Pipeline / Unit Tests (push) Successful in 19m54s
CI/CD Pipeline / Validate - Security (push) Successful in 26m55s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-10 23:39:21 +08:00
Agent 652d2cd270 Merge pull request #2256: 爆款视频多角色对话短剧+多音色配音
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 5s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
2026-10-10 23:38:47 +08:00
xiaoxia 019bbe6897 fix(ci): pin mypy<1.19 to avoid librt dependency (aliyun mirror missing librt-0.6.0 metadata)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m7s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m22s
AI Code Review / AI Code Review (pull_request) Successful in 7m4s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 17s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 17s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 11m11s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 10m39s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 13m36s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 11m10s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 19m22s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 28m12s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
2026-10-10 22:59:25 +08:00
xiaoxia f25fa9d978 fix(ci): pin mypy<1.19 to avoid librt dependency (aliyun mirror missing librt-0.6.0 metadata)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 6s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m58s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m9s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 47s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 26s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m9s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 13s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m32s
AI Code Review / AI Code Review (pull_request) Successful in 7m8s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 11m26s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 10m47s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 13m15s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 11m9s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 21m14s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 28m59s
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
2026-10-10 22:58:53 +08:00
saas-backend 2080ecc4f9 ci: 触发bc45a10 staging部署(PR#2265合并漏触发补跑)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 38s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m14s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 21s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m16s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 41s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m46s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m0s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m33s
AI Code Review / AI Code Review (pull_request) Successful in 7m7s
CI/CD Pipeline / Validate - Style (push) Successful in 12m0s
CI/CD Pipeline / Integration Tests (push) Successful in 11m6s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Failing after 13m51s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m46s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m8s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m58s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 4m7s
CI/CD Pipeline / Unit Tests (push) Successful in 23m2s
CI/CD Pipeline / Validate - Security (push) Successful in 31m20s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
2026-10-10 22:55:06 +08:00
xiaoxia bc45a10fff Merge pull request 'fix(viral-video): 审计第二轮修复 - 重试死循环/错误块串台/REVIEW审核/轮询熔断/WS终态' (#2265) from fix/viral-video-error-attribution into develop
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Has been cancelled
CI/CD Pipeline / Check if frontend-only change (push) Has been cancelled
CI/CD Pipeline / Validate - Style (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (push) Has been cancelled
CI/CD Pipeline / PR Build API Image (push) Has been cancelled
CI/CD Pipeline / PR Build Web Image (push) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (push) Has been cancelled
CI/CD Pipeline / Check push changed paths (push) Has been cancelled
CI/CD Pipeline / Build Staging API Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Lint (pull_request) Has been cancelled
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / PR Build API Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Web Image (pull_request) Has been cancelled
CI/CD Pipeline / PR Build Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
PR Automation / Auto Approve on CI Green (pull_request) Has been cancelled
Preview Deploy / Deploy Preview Environment (pull_request) Has been cancelled
2026-10-10 22:49:05 +08:00
CI Bot a949426100 fix(viral-video): 审计第二轮修复 - 重试死循环/错误块串台/REVIEW审核/轮询熔断/WS终态
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m49s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 21s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 4m10s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m53s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 44s
AI Code Review / AI Code Review (pull_request) Successful in 6m43s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m18s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 52s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m19s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
P0-2 [后端] /retry 接口入队改为 run_viral_video_analyze(从阶段1重跑),清空上一次产物字段(intent_result/copy_result/storyboard/result_video_url 等),避免重试后跑旧一键流水线卡死在 wait_user_confirm
P0-1 [前端] 合并两个错误块为单一 activeError 源,按 stage 显示前缀(图片分析/文案/视频独立);新增 analysisError 字段;所有 catch 分支互清残留;删除左侧文案区错误块避免双块串台
P1-1 [后端] 旧 pipeline + resume_pipeline 的外层 except 补 DB 兜底读 current_stage,避免 stage="" 导致错误归因错误
P1-2 [前端] REVIEW 合规审核失败跳回 step2_copy_ready 而非 failed 态,显示 warning 让用户修改文案
P1-3 [后端] resume_from_copy_generated 补清空 error_msg/result_video_url/current_stage/phase_message/completed_at/credits_cost
P1-4 [前端] activeError 派生时去掉后端已有的'XX失败'前缀,避免重复显示
P1-5 [前端] 删除 handleGenerateVideo 的 /generate 死路径(旧流水线出不了视频),改为提示'请先生成文案'
P2-5 [前端] 轮询连续失败20次(~2分钟)后熔断停止
P2-6 [前端+hook] WebSocket 收到 copy_generated/completed/failed 终态时主动拉取 job 一次,降低终态延迟
P3-1 [后端] _hb_thread 未使用变量改为 _

测试:249 viral 相关后端测试通过,tsc --noEmit 0 错误(除pre-existing marked模块),22 前端测试通过
2026-10-10 22:47:54 +08:00
xiaoxia e22a62802d fix(ci): mypy install add pip index fallback (aliyun->tsinghua->pypi) for librt 404
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m9s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m15s
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 15s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m33s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 12m7s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 12m45s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 15m16s
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled
2026-10-10 22:31:06 +08:00
xiaoxia 70d4a21055 fix(ci): mypy install add pip index fallback (aliyun->tsinghua->pypi) for librt 404
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m39s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m54s
AI Code Review / AI Code Review (pull_request) Successful in 6m51s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m12s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 34s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m30s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 1m4s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m48s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 12m25s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Successful in 11m22s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 11m7s
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
2026-10-10 22:29:33 +08:00
xiaoxia d6e4a09628 Merge pull request 'fix(viral-video): 修复文案/视频错误串台+字段名不匹配(BUG2)' (#2263) from fix/viral-video-error-attribution into develop
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m46s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m14s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 46s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m9s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m16s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 17s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m41s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 31s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 2m0s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (push) Successful in 11m47s
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Failing after 14m2s
CI/CD Pipeline / Integration Tests (push) Successful in 15m56s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been cancelled
2026-10-10 22:24:08 +08:00
CI Bot adcb59b446 fix(viral-video): 修复文案/视频错误串台 + 字段名不匹配导致所有错误归为文案失败
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 1m48s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m52s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 13s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m27s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m14s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m14s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m43s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m11s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 4m7s
AI Code Review / AI Code Review (pull_request) Successful in 7m16s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 41s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 11m52s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 12m44s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 14m33s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 21m51s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 30m22s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 3s
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
P0 根因:
- 后端 API 返回 current_stage/phase_message,但前端 types 只声明 progress_stage/progress_message,导致 isVideoStage/isCopyStage 永远判断为 false,所有失败都被归为 copyError
- mark_failed() 不持久化 current_stage,失败后 DB 中阶段丢失,进一步加剧归因错误
- onPollUpdate 中 copyError/videoError 的三元表达式是死代码(两边返回相同值)
- DashScope 异步任务失败时错误文案带 "HTTP 200",让用户误以为请求成功但被拦截

修复内容:
- 后端:ViralVideoJob.mark_failed(stage=) 持久化失败阶段;_mark_failed_and_notify 两处调用传 stage 参数
- 前端 types:补全 current_stage/phase_message 字段,新增 getJobStage/getJobPhaseMessage helper 兼容新旧字段
- 前端 onPollUpdate:用 helper 读阶段;正确归因 copyError/videoError;成功/运行态清理旧错误;删除冗余三元
- 前端 handleRetry:根据失败阶段跳回对应 UI step,不再一律跳 step3
- DashScope 错误提示:异步任务失败时不再显示误导性的 "HTTP 200"
- 所有现有单测通过(216 后端 + 3 前端)
2026-10-10 22:20:39 +08:00
Agent 213e89f93a fix: 恢复 rebase 后丢失的 renderVoiceoverWithSpeakers 函数定义
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 5s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m49s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 4m55s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m41s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m29s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m0s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 7m31s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 4m4s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 4m3s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 14m56s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m45s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 14m46s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 14m44s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 23m32s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 33m44s
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
2026-10-10 21:52:04 +08:00
Agent 79696e18f0 fix: 修复 integration tests - migration 105 兼容 storyboard v4
问题:105_narration_first.py 硬编码查找 storyboard v3,
但 DEFAULT_TEMPLATES 已升级为 v4,导致 RuntimeError。

修复:_tpl() 函数找不到指定版本时 fallback 到最新版本。
2026-10-10 21:52:04 +08:00
Agent 8ff9ab0cb4 fix: 修复 CI 第二轮红灯 - 类型错误修复
1. ShotScript 类型添加 speaker 字段
2. 移除 (s as any) 类型转换
3. textarea defaultValue 改为字符串(非 React 元素)
2026-10-10 21:52:04 +08:00
Agent f10b5393fa fix: 修复 CI 红灯 - Alembic down_revision 错误 + 前端未使用变量 2026-10-10 21:52:04 +08:00
Agent ba0e3fc67f fix: 修复 _script_from_xml 中 speaker 变量未定义即使用的 bug 2026-10-10 21:52:04 +08:00
xiaoxia 6eb528ed44 Merge pull request 'fix(ci): staging部署脚本web容器nginx conf补WS透传+3600s' (#2262) from fix/ci-staging-deploy-nginx-ws into develop
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m32s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m54s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m47s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 27s
AI Code Review / AI Code Review (pull_request) Successful in 6m53s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 25s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m34s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 40s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m51s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m37s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 1m26s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m37s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m16s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Failing after 12m33s
CI/CD Pipeline / Validate - Style (push) Successful in 14m34s
CI/CD Pipeline / Integration Tests (push) Successful in 13m25s
CI/CD Pipeline / Unit Tests (push) Successful in 22m30s
CI/CD Pipeline / Validate - Security (push) Successful in 36m7s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-10 21:39:20 +08:00
saas-backend 82ba481e4f fix(ci): staging部署脚本生成的web容器nginx conf补WS透传+3600s超时
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 54s
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m18s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m31s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m40s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m20s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m30s
AI Code Review / AI Code Review (pull_request) Successful in 7m22s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 42s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 13m46s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 14m32s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 15m12s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 24m25s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 37m18s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 1s
真staging(116.62)的web容器conf由ci_staging_deploy.sh heredoc每次部署重新生成,
此前缺Upgrade/Connection头导致wss握手被剥头404,且300s超时会断WS长连接。
本次在heredoc模板/api/块补Upgrade两行+3600s,与PR#2259/#2260对齐,防部署回退。
2026-10-10 21:39:11 +08:00
xiaoxia 5864ab0325 feat(viral-video): 三列卡片等高+内容区内部滚动 (#2261)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 3s
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 52s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 42s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Successful in 30s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m56s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m14s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m23s
CI/CD Pipeline / CI Gate (pull_request) Successful in 6s
CI/CD Pipeline / Retag skipped Staging API Image (push) Successful in 1m52s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 4m36s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 2m31s
AI Code Review / AI Code Review (pull_request) Successful in 7m26s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m38s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 2m7s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m12s
CI/CD Pipeline / Integration Tests (push) Successful in 13m28s
CI/CD Pipeline / Validate - Style (push) Successful in 14m27s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 17m28s
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
feat(viral-video): 三列卡片等高+内容区内部滚动

- vv-page 设置固定视口高度 flex 列布局
- vv-grid align-items:stretch + grid-auto-rows:1fr 强制三列等高
- vv-section-body-scroll + vv-scroll-inner 包裹 STEP1/2/3 内容区,超高度内部滚动
- 滚动条美化(紫色细滚动条)
- vv-storyboard/vv-copy-loading/vv-copy-box 改用 flex:1 自适应高度
- STEP3 预览区 vv-section-preview 吸剩余空间
- 主按钮固定在卡片底部不被滚走

前端-only PR,Python mypy 失败属 pre-existing
2026-10-10 21:20:09 +08:00
19 changed files with 941 additions and 129 deletions
+1 -2
View File
@@ -1,2 +1 @@
CI trigger file - safe to delete
retrigger at 2026-09-15 20:31:24 UTC
trigger staging deploy for bec75a07 (viral-video error isolation) at 2026-10-11 19:39:29
+8 -1
View File
@@ -28,10 +28,17 @@ depends_on = None
def _tpl(prompt_type: str, version: int) -> dict:
"""取模板:先按指定版本找,找不到则取该类型最新版本(兼容 v3→v4 升级)。"""
# 先按指定版本找
for t in DEFAULT_TEMPLATES:
if t["prompt_type"] == prompt_type and t["version"] == version:
return t
raise RuntimeError("default template missing: %s v%s" % (prompt_type, version))
# 找不到则取最新版本
candidates = [t for t in DEFAULT_TEMPLATES if t["prompt_type"] == prompt_type]
if candidates:
latest = max(candidates, key=lambda x: x["version"])
return latest
raise RuntimeError("default template missing: %s" % prompt_type)
def _upsert(bind, t: dict) -> None:
@@ -0,0 +1,235 @@
# -*- coding: utf-8 -*-
"""storyboard v4 - 多角色对话 + 废除旁白 + visual 5要素
Revision ID: 108_storyboard_v4_multivoice
Revises: 107
Create Date: 2026-10-10
变更:
1. storyboard v4: 废除旁白思维,所有voiceover必须是角色台词
- 增加<speaker>标签,每镜必须标注说话人
- visual强制5要素结构(景别/运镜/动作/环境/光线),每镜不少于30字
- voiceover_script用[speaker:xxx]标记格式
2. 旧版storyboard模板is_active设为false
3. 检查image_analysis和review是否有active模板,没有则插入保底版本
"""
from sqlalchemy import text
from alembic import op
revision = "108_storyboard_v4_multivoice"
down_revision = "107"
branch_labels = None
depends_on = None
# ── storyboard v4 system_prompt ──────────────────────────────────────
V4_STORYBOARD_SYSTEM = """你是一名懂短视频的编导和口播文案高手。你会拿到图片的真实观察、营销目的和用户参数,请一次性完成对营销意图的理解,并产出可直接拍摄/生成的分镜脚本。不要单独输出"意图解析",意图要直接体现在台词和分镜里。
## 核心设计原则(必须严格遵守)
1. **废除旁白思维**:所有视频类型——无论对话短剧/口播带货/获客引流/品牌故事——voiceover 必须是人物说的话(第一人称或角色对白),绝对不能出现第三人称旁白解说。观众看的是人在演、在说。
2. **严禁第三人称解说性台词**:如"接下来展示...""这款产品..."这类上帝视角描述禁止出现在 voiceover 中。
3. **短剧类营销目的**(对话短剧/反转短剧/悬念短剧/情绪短片):双角色对话格式"甲:xxx 乙:xxx",镜头在角色间切换。
4. **口播类**(口播带货/促销转化/功能演示/痛点解决/获客引流/账号涨粉/活动通知/场景种草):第一人称对镜头说话,像真人出镜。
## 输出格式(XML,严格按结构输出,不要输出额外解释)
<script>
<copy_display_markdown><![CDATA[直接展示给用户看的成片文案,用 Markdown 写成流畅叙述]]></copy_display_markdown>
<clips>
<clip index="1">
<time_range>0-3秒</time_range>
<speaker>说话人标识(如"店主""顾客""主播")</speaker>
<voiceover>这一镜的角色台词(人物说的话,不是旁白)</voiceover>
<visual>【景别】【镜头运动】【人物动作/表情】【环境/道具】【光线氛围】5要素结构,不少于30字</visual>
<reference_image_index>0</reference_image_index>
</clip>
</clips>
<voiceover_script>把所有 clip 的 voiceover 连成完整台词稿,用 [speaker:xxx] 标记每个说话段落</voiceover_script>
<theme>一句话主题</theme>
<negative>【反套路化要求】
禁止使用"家人们谁懂啊""绝绝子""宝子们""家人们""太绝了""yyds"等烂大街网络词;
禁止固定模板化开头;语言要像真人朋友之间的分享,自然、具体、有信息量。</negative>
</script>
## 写作要求
1. **台词(voiceover)**:像真人面对镜头说话或角色对白,短句、口语化、有停顿有情绪,开头 3 秒给出钩子;不要书面腔,不要机械报参数。严禁第三人称解说。
2. **说话人(speaker)**:每个 clip 必须标注说话人标识,如"店主""顾客""主播""我"等。短剧类必须有至少 2 个不同角色。
3. **画面描述(visual)**:强制 5 要素结构——【景别】【镜头运动】【人物动作/表情】【环境/道具】【光线氛围】,每镜 visual 不少于 30 字,要具体到"闭眼听台词能想象出画面"。
4. **voiceover_script 格式**:用 [speaker:xxx] 标记每个说话段落,如"[speaker:店主]你是不是也觉得...[speaker:顾客]是啊,怎么回事?"
5. copy_display_markdown:直接展示给最终用户的文案,用 Markdown 写成自然、流畅、有感染力的成片文案。
6. 内容必须来自图片观察与用户给出的信息,不编造卖点、不夸大、不使用绝对化用语和虚假承诺。
7. reference_image_index 填本镜参考图片序号(从 0 开始),没有合适参考图填 -1。
8. 分镜数量与时长匹配总时长,节奏紧凑。
9. **口播字数硬约束**(必须严格遵守):按每秒约 2.5~3 个中文字(正常口播语速)计算:
- 5秒视频:voiceover_script 总字数 12~15 字
- 10秒视频:voiceover_script 总字数 25~30 字
- 15秒视频:voiceover_script 总字数 35~45 字
- 20秒视频:voiceover_script 总字数 50~60 字
- 30秒视频:voiceover_script 总字数 75~90 字
- 宁可少写也不要多写,超长会导致 TTS 音频超出视频时长限制
10. **镜头数量硬约束**:5秒1~2镜、10秒3镜、15秒3~4镜、20秒4~5镜、30秒6~8镜
11. **时间轴硬约束**:第一个clip从0秒开始,最后一个clip结束于total_duration秒,相邻clip首尾相接
12. 必须严格按<marketing_purpose><target_audience><persona><viral_structure><language><industry>指定的参数写文案和分镜
13. 镜头间动作衔接要自然,画面描述要具体到能直接拍摄/生成"""
V4_STORYBOARD_USER = """<marketing_purpose>{marketing_purpose}</marketing_purpose>
<industry>{industry}</industry>
<image_analysis>
{image_summary}
</image_analysis>
<user_parameters>
<theme_hint>{theme_hint}</theme_hint>
<duration>{duration}秒</duration>
<aspect_ratio>{aspect_ratio}</aspect_ratio>
<tone>{tone}</tone>
<target_audience>{target_audience}</target_audience>
<persona>{persona_hint}</persona>
<viral_structure>{viral_structure_hint}</viral_structure>
<language>{language_hint}</language>
<extra_requirements>{extra_requirements}</extra_requirements>
</user_parameters>
{video_style_section}
请严格按 XML 结构输出分镜脚本。"""
V4_STORYBOARD_EXAMPLE = """<script>
<copy_display_markdown><![CDATA[# 在御众堂,把松弛的自己一点点找回来
产后妈妈最懂那种力不从心,推开门,暖光和一杯热茶先接住了你……]]></copy_display_markdown>
<clips>
<clip index="1">
<time_range>0-3秒</time_range>
<speaker>店主</speaker>
<voiceover>生完娃,是不是连照镜子的勇气都没了?</voiceover>
<visual>【中近景】【缓推】【妈妈疲惫看向镜子】【暖光店内环境】【柔和暖光】</visual>
<reference_image_index>0</reference_image_index>
</clip>
<clip index="2">
<time_range>3-6秒</time_range>
<speaker>顾客</speaker>
<voiceover>是啊,怎么回事?</voiceover>
<visual>【近景】【固定】【顾客表情惊讶】【店内休息区】【暖色调】</visual>
<reference_image_index>0</reference_image_index>
</clip>
</clips>
<voiceover_script>[speaker:店主]生完娃,是不是连照镜子的勇气都没了?[speaker:顾客]是啊,怎么回事?</voiceover_script>
<theme>产后妈妈走进御众堂重拾状态</theme>
<negative>模糊、畸变、夸大疗效、绝对化用语</negative>
</script>"""
def upgrade() -> None:
conn = op.get_bind()
# 1. 查询 storyboard 当前最大 version
result = conn.execute(
text("SELECT MAX(version) FROM viral_video_prompt_templates WHERE prompt_type = :pt"),
{"pt": "storyboard"},
)
max_version = result.scalar() or 0
new_version = max_version + 1
# 2. 旧版 storyboard 模板 is_active 设为 false
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active = false WHERE prompt_type = :pt"),
{"pt": "storyboard"},
)
# 3. 防御性插入新版 storyboard 模板
existing = conn.execute(
text("SELECT id FROM viral_video_prompt_templates " "WHERE prompt_type = :pt AND version = :ver"),
{"pt": "storyboard", "ver": new_version},
).fetchone()
if not existing:
conn.execute(
text(
"INSERT INTO viral_video_prompt_templates "
"(name, prompt_type, version, system_prompt, user_prompt_template, example_output, is_active) "
"VALUES (:name, :pt, :ver, :sys, :usr, :ex, :active)"
),
{
"name": "编导分镜v4-多角色对话版",
"pt": "storyboard",
"ver": new_version,
"sys": V4_STORYBOARD_SYSTEM,
"usr": V4_STORYBOARD_USER,
"ex": V4_STORYBOARD_EXAMPLE,
"active": True,
},
)
# 4. 检查 image_analysis 是否有 active 模板,没有则插入保底
ia_active = conn.execute(
text("SELECT COUNT(*) FROM viral_video_prompt_templates WHERE prompt_type = :pt AND is_active = true"),
{"pt": "image_analysis"},
).scalar()
if ia_active == 0:
# 插入保底 image_analysis 模板(简化版)
ia_max = (
conn.execute(
text("SELECT MAX(version) FROM viral_video_prompt_templates WHERE prompt_type = :pt"),
{"pt": "image_analysis"},
).scalar()
or 0
)
conn.execute(
text(
"INSERT INTO viral_video_prompt_templates "
"(name, prompt_type, version, system_prompt, user_prompt_template, example_output, is_active) "
"VALUES (:name, :pt, :ver, :sys, :usr, :ex, :active)"
),
{
"name": "图片分析保底版",
"pt": "image_analysis",
"ver": ia_max + 1,
"sys": "你是一名擅长观察和写作的品牌内容编导。分析图片并输出JSON。",
"usr": "请分析这张图片。图片地址:{image_url}",
"ex": '{"images": [{"type": "store", "name": "门店", "summary_markdown": "描述"}]}',
"active": True,
},
)
# 5. 检查 review 是否有 active 模板
review_active = conn.execute(
text("SELECT COUNT(*) FROM viral_video_prompt_templates WHERE prompt_type = :pt AND is_active = true"),
{"pt": "review"},
).scalar()
if review_active == 0:
rv_max = (
conn.execute(
text("SELECT MAX(version) FROM viral_video_prompt_templates WHERE prompt_type = :pt"),
{"pt": "review"},
).scalar()
or 0
)
conn.execute(
text(
"INSERT INTO viral_video_prompt_templates "
"(name, prompt_type, version, system_prompt, user_prompt_template, example_output, is_active) "
"VALUES (:name, :pt, :ver, :sys, :usr, :ex, :active)"
),
{
"name": "文案审核保底版",
"pt": "review",
"ver": rv_max + 1,
"sys": "你是短视频广告合规审核专家。审核文案输出XML。",
"usr": "请审核:{fusion_text}",
"ex": "<review><passed>true</passed></review>",
"active": True,
},
)
def downgrade() -> None:
# 恢复旧版 storyboard 为 active
conn = op.get_bind()
conn.execute(
text("UPDATE viral_video_prompt_templates SET is_active = true WHERE prompt_type = :pt AND version < :ver"),
{"pt": "storyboard", "ver": 4},
)
# 删除新版
conn.execute(
text("DELETE FROM viral_video_prompt_templates WHERE prompt_type = :pt AND version >= :ver"),
{"pt": "storyboard", "ver": 4},
)
+25 -5
View File
@@ -1,9 +1,10 @@
"""Ditto 数字人表情后台配置 — #2246.
路由前缀 /api/v1/admin/ditto-emotion,全部使用 _verify_internal_api_key 鉴权
(X-API-Key header)。仅开放 5 项白名单配置:
(X-API-Key header)。仅开放 6 项白名单配置:
- ditto_emotion_enabled / ditto_emotion_model / ditto_emotion_temperature
- ditto_emotion_prompt / ditto_blend_frames
- ditto_emotion_prompt / ditto_blend_frames / doubao_api_key
注意:doubao_api_key 属于密钥,GET 只返回脱敏占位,绝不返回明文。
"""
from __future__ import annotations
@@ -43,6 +44,7 @@ _WHITELIST: dict[str, str] = {
"ditto_emotion_temperature": SETTING_TYPE_FLOAT,
"ditto_emotion_prompt": SETTING_TYPE_STRING,
"ditto_blend_frames": SETTING_TYPE_INT,
"doubao_api_key": SETTING_TYPE_STRING,
}
_DESCRIPTIONS: dict[str, str] = {
@@ -51,8 +53,13 @@ _DESCRIPTIONS: dict[str, str] = {
"ditto_emotion_temperature": "模型温度,0-1,越低越稳定保守。",
"ditto_emotion_prompt": "情绪分析提示词,核心调优入口,必须包含 {文案} 占位符。",
"ditto_blend_frames": "表情切换过渡帧数(6-30),越大越柔和。",
"doubao_api_key": "豆包/火山方舟 API Key(用于情绪分析LLM调用)",
}
# 密钥类配置:GET 脱敏、PUT 响应不回显明文
_SECRET_KEYS = {"doubao_api_key"}
_SECRET_PLACEHOLDER = "***已配置***"
def _settings():
return get_api_settings()
@@ -63,13 +70,24 @@ def _default_value(key: str) -> Any:
def _build_config_item(key: str) -> dict[str, Any]:
service = get_system_config_service()
if key in _SECRET_KEYS:
# 密钥不回明文、不暴露 env 默认值:DB 或 env 任一侧已配置即视为已配置
db_value = service.get_config(key, None)
configured = bool((db_value or "").strip()) or bool((getattr(_settings(), key, "") or "").strip())
return {
"key": key,
"type": _WHITELIST[key],
"description": _DESCRIPTIONS.get(key, ""),
"default": "",
"value": _SECRET_PLACEHOLDER if configured else "",
}
item: dict[str, Any] = {
"key": key,
"type": _WHITELIST[key],
"description": _DESCRIPTIONS.get(key, ""),
"default": _default_value(key),
}
service = get_system_config_service()
item["value"] = service.get_config(key, _default_value(key))
if key == "ditto_emotion_model":
item["model_options"] = list(MODEL_OPTIONS)
@@ -110,6 +128,8 @@ def _validate_value(key: str, value: Any) -> Any:
raise ValueError("提示词必须包含 {文案} 占位符")
if key == "ditto_emotion_model" and value not in MODEL_OPTIONS:
raise ValueError(f"模型必须是以下之一:{', '.join(MODEL_OPTIONS)}")
if key == "doubao_api_key" and not value.strip():
raise ValueError(f"{key} 不能为空字符串")
return value
@@ -141,9 +161,9 @@ def update_config(
key,
value,
setting_type=_WHITELIST[key],
updated_by=x_api_key[:8] if x_api_key else None,
updated_by=str(x_api_key)[:8] if x_api_key and x_api_key is not True else None,
)
updated[key] = value
updated[key] = _SECRET_PLACEHOLDER if key in _SECRET_KEYS else value
return {"ok": True, "updated": updated}
+12 -3
View File
@@ -701,7 +701,7 @@ def retry_viral_video_job(
)
# 差额为 0 则不调整
# 重置状态
# 重置状态(从阶段1重新开始,清空上一次产物避免脏数据)
job.retry_count += 1
job.status = ViralVideoStatus.PENDING
job.error_msg = "" if not is_stale_running else "任务执行超时,已重置重试"
@@ -710,11 +710,20 @@ def retry_viral_video_job(
job.current_stage = ""
job.phase_message = ""
job.heartbeat_at = None
# 重试时清空上次产物(参考 resume_from_image_analyzed 逻辑)
job.intent_result = None
job.copy_result = None
job.storyboard = None
job.generated_copy_text = ""
job.result_video_url = ""
job.pre_trusted_images = None
job.credits_cost = 0.0
repo.update(job)
# 重新入队
# 重新入队:从图片分析阶段1重新跑(旧 run_viral_video_pipeline 只跑到 wait_user_confirm 就停,
# 会导致前端永远转圈或文案确认页卡死后 confirm-copy 返回 409)
try:
celery_app.send_task("worker.run_viral_video_pipeline", args=[job.id])
celery_app.send_task("worker.run_viral_video_analyze", args=[job.id])
logger.info(
"[爆款视频] 重试入队: job_id=%s retry_count=%d stale=%s params_changed=%s",
job.id,
+24
View File
@@ -65,6 +65,22 @@ export function isAnalysisStage(stage: ViralVideoStage | undefined): boolean {
return isImageAnalysisStage(stage) || isCopyStage(stage)
}
/** 从 job 对象取到有效阶段(兼容 progress_stage/current_stage 两种字段名) */
export function getJobStage(
job: { current_stage?: ViralVideoStage; progress_stage?: ViralVideoStage } | null | undefined,
): ViralVideoStage | undefined {
if (!job) return undefined
return job.current_stage || job.progress_stage
}
/** 从 job 对象取到阶段提示文案(兼容 phase_message/progress_message) */
export function getJobPhaseMessage(
job: { phase_message?: string; progress_message?: string } | null | undefined,
): string {
if (!job) return ""
return job.phase_message || job.progress_message || ""
}
/** 单张图片 VLM 识别结果(v8 叙述优先,仅保留最少结构化字段) */
export interface ImageProductAnalysis {
/** store / product / person / scene */
@@ -89,6 +105,8 @@ export interface ImageAnalysisResult {
export interface ShotScript {
/** 时间区间,如 "0-3秒" */
time_range?: string
/** 说话人角色,如 "店主"、"顾客" */
speaker?: string
/** 景别/角度/运镜,如 "近景俯拍45度,缓慢推镜" */
shot_type_angle_movement?: string
/** 场景描述+对白 */
@@ -189,8 +207,14 @@ export interface ViralVideoJob {
video_model?: string
/** 视频时长(秒,5-30,默认15) */
duration?: number
/** 后端真实字段名(snake_case):当前细粒度阶段 */
current_stage?: ViralVideoStage
/** 后端真实字段名:当前阶段中文提示文案 */
phase_message?: string
/** @deprecated 兼容旧前端:使用 current_stage */
progress_stage?: ViralVideoStage
progress_percent?: number
/** @deprecated 兼容旧前端:使用 phase_message */
progress_message?: string
output_url?: string
result_video_url?: string
+226 -71
View File
@@ -37,6 +37,8 @@ import {
isVideoStage,
isCopyStage,
isImageAnalysisStage,
getJobStage,
getJobPhaseMessage,
type FusionLevel,
type StyleStrength,
type ViralVideoJob,
@@ -47,13 +49,13 @@ import {
type ViralVideoModel,
} from "@/api/viral-video/types"
import {
generateViralVideo,
retryViralVideo,
analyzeViralImages,
generateViralCopy,
confirmViralCopy,
estimateViralVideoCredits,
getViralVideoModels,
getViralVideoJob,
} from "@/api/viral-video"
import { useViralVideoPolling } from "./hooks/useViralVideoPolling"
import { useViralVideoWS, type ViralVideoDeltaEvent } from "./hooks/useViralVideoWebSocket"
@@ -145,6 +147,7 @@ type TabTask = {
voiceTipsOpen: boolean
copyError?: string
videoError?: string
analysisError?: string
// 运行态(后端 job)
job: ViralVideoJob | null
jobId: string | null
@@ -295,9 +298,33 @@ const UPSCALE_OPTIONS = [
const VOICE_TIPS =
"支持 MP3/WAV/M4A/AAC/OGG 格式,最大 10MB,时长 ≤30 秒。建议清晰人声、无背景音乐、环境安静;录音请保持距麦克风 15-20cm,音量适中。"
/** 解析 voiceover_script 中的 [speaker:xxx] 标记,渲染为带颜色的 React 片段 */
function renderVoiceoverWithSpeakers(text: string) {
if (!text) return null
const parts = text.split(/\[speaker:([^\]]+)\]/)
if (parts.length === 1) {
// 没有 speaker 标记,直接显示
return <span>{text}</span>
}
const elements: React.ReactNode[] = []
for (let i = 1; i < parts.length; i += 2) {
const speaker = parts[i]
const segText = parts[i + 1] || ""
const isMain = ["店主", "主播", "老板", "我", "主讲人"].includes(speaker)
elements.push(
<span key={i}>
<strong style={{ color: isMain ? "#1890ff" : "#fa8c16" }}>{speaker}</strong>
<span>{segText}</span>
</span>,
)
}
return <>{elements}</>
}
// ── 分镜脚本数据模型(新后端 copy_result 结构,前端先 mock 展示) ──
interface StoryboardShot {
time_range: string
speaker?: string
shot_type_angle_movement: string
scene_and_dialogue: string
action_details: string
@@ -330,6 +357,7 @@ function copyResultToStoryboard(cr: CopyResult | null | undefined): Storyboard |
scene_and_lighting: cr.scene_and_lighting || "",
shots: ((cr.shots ?? []) as ShotScript[]).map((s) => ({
time_range: s.time_range || "",
speaker: s.speaker || "",
shot_type_angle_movement: s.shot_type_angle_movement || "",
scene_and_dialogue: s.scene_and_dialogue || "",
action_details: s.action_details || "",
@@ -632,6 +660,7 @@ const ViralVideoPage: React.FC = () => {
let nextStep: UIStep = t.uiStep
let copyError = t.copyError
let videoError = t.videoError
let analysisError = t.analysisError
const err = job.error_message || job.error_msg
// 同步服务端最新的分析/文案结果(若已返回)
const nextImageAnalysis = job.image_analysis || t.imageAnalysis
@@ -641,12 +670,17 @@ const ViralVideoPage: React.FC = () => {
? copyResultToStoryboard(nextCopy) || t.storyboard
: t.storyboard
// BUG 修复:后端真实字段是 current_stage(不是 progress_stage),用 helper 兼容两种字段
const stage = getJobStage(job)
switch (job.status) {
case "image_analyzed":
nextStep = "step1_done"
copyError = undefined
break
case "copy_generated":
nextStep = "step2_copy_ready"
copyError = undefined
break
case "wait_user_confirm":
// 兼容旧链路:停在等待确认
@@ -656,20 +690,49 @@ const ViralVideoPage: React.FC = () => {
: "step2_copy_ready"
break
case "running":
if (isVideoStage(job.progress_stage)) nextStep = "step3_generating"
else if (isCopyStage(job.progress_stage)) nextStep = "step2_generating"
else if (isImageAnalysisStage(job.progress_stage)) nextStep = "step1_analyzing"
if (isVideoStage(stage)) nextStep = "step3_generating"
else if (isCopyStage(stage)) nextStep = "step2_generating"
else if (isImageAnalysisStage(stage)) nextStep = "step1_analyzing"
copyError = undefined
videoError = undefined
break
case "completed":
nextStep = "step3_done"
copyError = undefined
videoError = undefined
break
case "failed":
case "failed": {
// P1-2:REVIEW 阶段合规审核失败,跳回文案确认页让用户修改,不走 failed 态
if (stage === "review" && err && (err.includes("合规") || err.includes("审核未通过"))) {
nextStep = "step2_copy_ready"
copyError = undefined
videoError = undefined
message.warning(err)
break
}
nextStep = "failed"
if (isVideoStage(job.progress_stage)) videoError = err || videoError
else copyError = err || copyError
// 根据 current_stage 正确归因错误(图片/文案/视频错误独立显示)
// 兜底:若 stage 丢失但错误消息含视频生成相关关键词,归为视频错误
const looksLikeVideoErr =
/wan 3\.0|seedance|视频生成|视频下载|视频渲染|tts|配音|render/i.test(err || "")
const looksLikeImageErr =
/vlm|图片分析|vision|商品识别|ocr|image analysis|图片识别/i.test(err || "")
if (isVideoStage(stage) || (!isImageAnalysisStage(stage) && !isCopyStage(stage) && looksLikeVideoErr)) {
videoError = err || videoError || "视频生成失败"
copyError = undefined
analysisError = undefined
} else if (isImageAnalysisStage(stage) || looksLikeImageErr) {
analysisError = err || analysisError || "图片分析失败"
copyError = undefined
videoError = undefined
} else {
copyError = err || copyError || "文案生成失败"
videoError = undefined
analysisError = undefined
}
break
}
case "pending":
// 保持当前加载态
break
}
return {
@@ -678,10 +741,9 @@ const ViralVideoPage: React.FC = () => {
uiStep: nextStep,
imageAnalysis: nextImageAnalysis,
storyboard: nextStoryboard,
copyError:
nextStep === "failed" && isCopyStage(job.progress_stage) ? copyError : copyError,
videoError:
nextStep === "failed" && isVideoStage(job.progress_stage) ? videoError : videoError,
copyError,
videoError,
analysisError,
}
})
},
@@ -704,6 +766,16 @@ const ViralVideoPage: React.FC = () => {
)
useViralVideoWS(task.uiStep === "step2_generating" ? task.jobId : null, {
onDelta: onScriptDelta,
// P2-6: WS 收到终态事件时立即主动拉取 job,降低终态延迟
onTerminal: async (ev) => {
if (!ev.job_id) return
try {
const job = await getViralVideoJob(ev.job_id)
onPollUpdate(job)
} catch (e) {
console.warn("[viral-video] WS终态主动拉取失败,等待HTTP轮询兜底", e)
}
},
})
// 进入/离开"文案生成中"时重置流式缓冲,避免上一个任务的残留
@@ -1064,7 +1136,17 @@ const ViralVideoPage: React.FC = () => {
message.warning("参考视频上传中,请稍候")
return
}
setTask({ uiStep: "step1_analyzing", jobId: null, job: null })
// 开始新一轮图片分析:清空所有错误状态+旧产物,避免上一轮失败的错误残留显示
setTask({
uiStep: "step1_analyzing",
jobId: null,
job: null,
analysisError: undefined,
copyError: undefined,
videoError: undefined,
imageAnalysis: undefined,
storyboard: undefined,
})
try {
const job = await analyzeViralImages({
images: readyImgs.map((i) => i.ossUrl as string),
@@ -1076,7 +1158,12 @@ const ViralVideoPage: React.FC = () => {
message.success("已提交图片分析…")
} catch (err: unknown) {
message.error(err instanceof Error ? err.message : "分析失败")
setTask({ uiStep: "failed", copyError: err instanceof Error ? err.message : "分析失败" })
setTask({
uiStep: "failed",
analysisError: err instanceof Error ? err.message : "分析失败",
copyError: undefined,
videoError: undefined,
})
}
}
@@ -1087,7 +1174,7 @@ const ViralVideoPage: React.FC = () => {
message.warning("请先完成图片分析")
return
}
setTask({ uiStep: "step2_generating", copyError: undefined })
setTask({ uiStep: "step2_generating", copyError: undefined, videoError: undefined, analysisError: undefined })
try {
const job = await generateViralCopy(task.jobId, {
industry: task.industry || undefined,
@@ -1116,7 +1203,12 @@ const ViralVideoPage: React.FC = () => {
// 轮询会在 status=copy_generated 时推进 uiStep
} catch (err: unknown) {
message.error(err instanceof Error ? err.message : "文案生成失败")
setTask({ uiStep: "failed", copyError: err instanceof Error ? err.message : "文案生成失败" })
setTask({
uiStep: "failed",
copyError: err instanceof Error ? err.message : "文案生成失败",
videoError: undefined,
analysisError: undefined,
})
}
}
@@ -1126,7 +1218,7 @@ const ViralVideoPage: React.FC = () => {
* - 若 job 已在 copy_generated/image_analyzed 且文案已确认:重新调 confirm-copy
* - 其他情况:回退到旧的 /generate 全量提交(兼容旧任务/降级) */
const handleGenerateVideo = async () => {
setTask({ uiStep: "step3_generating", videoError: undefined })
setTask({ uiStep: "step3_generating", videoError: undefined, copyError: undefined, analysisError: undefined })
try {
let job
if (task.jobId && task.storyboard && task.storyboard.voiceover_script.trim()) {
@@ -1141,33 +1233,17 @@ const ViralVideoPage: React.FC = () => {
video_model: task.videoModel,
})
} else {
// 兜底:走旧 /generate 接口(一次性跑完)
const imgUrls = task.images
.filter((i) => i.ossUrl && !i.uploading)
.map((i) => i.ossUrl as string)
const payload: Parameters<typeof generateViralVideo>[0] = {
images: imgUrls,
reference_video_url: task.refVideo?.ossUrl || undefined,
style_strength: task.refVideo?.ossUrl ? task.styleStrength : undefined,
user_copy_text: task.storyboard?.voiceover_script || task.userCopy || undefined,
fusion_level: task.fusionLevel,
voice_id:
task.refAudio?.source === "preset"
? task.refAudio.id
: task.refAudio?.source === "my_voice"
? task.refAudio.ttsVoiceId || task.refAudio.id
: undefined,
voice_source: task.refAudio?.source,
industry: task.industry || undefined,
target_customer: task.targetCustomer || undefined,
language: task.language || undefined,
viral_structure: task.viralStructure || undefined,
marketing_purpose: task.marketingPurpose || undefined,
duration: task.duration,
video_model: task.videoModel,
video_ratio: task.videoRatio,
}
job = await generateViralVideo(payload)
// P1-5 修复:旧 /generate 接口只跑图片分析→wait_user_confirm 就停,永远出不了视频。
// 没有 storyboard 时直接提示用户先生成文案,不再走死路径。
message.warning("请先生成文案后再生成视频")
setTask({
uiStep: task.storyboard
? "step2_copy_ready"
: task.imageAnalysis
? "step1_done"
: "step1_upload",
})
return
}
setTask({ job, jobId: job.id })
message.success("视频已提交生成,预计 1-3 分钟…")
@@ -1181,12 +1257,17 @@ const ViralVideoPage: React.FC = () => {
?.message ||
"积分不足,请充值"
message.error(detail)
setTask({ uiStep: "step3_ready", videoError: detail })
setTask({
uiStep: "step3_ready",
videoError: detail,
copyError: undefined,
analysisError: undefined,
})
return
}
const msg = err instanceof Error ? err.message : "提交失败"
message.error(msg)
setTask({ uiStep: "failed", videoError: msg })
setTask({ uiStep: "failed", videoError: msg, copyError: undefined, analysisError: undefined })
}
}
@@ -1194,7 +1275,23 @@ const ViralVideoPage: React.FC = () => {
if (task.jobId) {
try {
const j = await retryViralVideo(task.jobId)
setTask({ job: j, uiStep: "step3_generating", videoError: undefined })
// BUG 修复:根据失败阶段跳回对应 UI step,不要一律跳到 step3
const retryStage = getJobStage(j)
let retryStep: UIStep = "step1_analyzing"
if (isVideoStage(retryStage)) retryStep = "step3_generating"
else if (isCopyStage(retryStage)) retryStep = "step2_generating"
else if (task.storyboard) retryStep = "step2_copy_ready"
else if (task.imageAnalysis) retryStep = "step1_done"
setTask({
job: j,
uiStep: retryStep,
videoError: undefined,
copyError: undefined,
analysisError: undefined,
// retry 从阶段1重新跑,清空旧产物避免残留
imageAnalysis: undefined,
storyboard: undefined,
})
message.success("已重试")
} catch (err: unknown) {
message.error(err instanceof Error ? err.message : "重试失败")
@@ -1205,6 +1302,9 @@ const ViralVideoPage: React.FC = () => {
uiStep: task.storyboard ? "step2_copy_ready" : "step1_done",
videoError: undefined,
copyError: undefined,
analysisError: undefined,
imageAnalysis: undefined,
storyboard: undefined,
})
}
}
@@ -1228,8 +1328,37 @@ const ViralVideoPage: React.FC = () => {
/* ── 派生状态 ── */
const outputUrl = task.job?.output_url || task.job?.result_video_url
const errMsg = task.videoError || task.job?.error_message || task.job?.error_msg
// 统一错误源:按优先级取第一个有值的错误,根据 stage 显示前缀(避免 videoError/copyError 双块串台)
const activeError = (() => {
if (task.videoError) return { stage: "video" as const, msg: task.videoError }
if (task.copyError) return { stage: "copy" as const, msg: task.copyError }
if (task.analysisError) return { stage: "image" as const, msg: task.analysisError }
const srv = task.job?.error_message || task.job?.error_msg
if (srv) {
// P1-4: 后端错误消息已含"XX失败"前缀时去重
const cleaned = srv.replace(
/^(视频生成失败|文案生成失败|图片分析失败|Wan 3\.0 视频生成失败)[::]\s*/g,
"",
)
const st = getJobStage(task.job)
// 兜底:基于错误消息关键词判定(防止 stage 字段为空时错误归到文案)
const looksLikeVideoErr =
/wan 3\.0|seedance|视频生成|视频下载|视频渲染|tts|配音|render/i.test(cleaned)
const looksLikeImageErr = /vlm|图片分析|vision|商品识别|ocr|image analysis|图片识别/i.test(cleaned)
if (isVideoStage(st) || looksLikeVideoErr) return { stage: "video" as const, msg: cleaned }
if (isImageAnalysisStage(st) || looksLikeImageErr) return { stage: "image" as const, msg: cleaned }
return { stage: "copy" as const, msg: cleaned }
}
return null
})()
const errLabel =
activeError?.stage === "image"
? "图片分析失败"
: activeError?.stage === "copy"
? "文案生成失败"
: activeError?.stage === "video"
? "视频生成失败"
: ""
const step2Enabled =
task.uiStep === "step1_done" ||
task.uiStep === "step2_generating" ||
@@ -1378,8 +1507,8 @@ const ViralVideoPage: React.FC = () => {
const hasStream = task.scriptStreamText.trim().length > 0
const stageMsg =
task.scriptStreamMessage ||
task.job?.progress_message ||
getCopyStageText(task.job?.progress_stage)
getJobPhaseMessage(task.job) ||
getCopyStageText(getJobStage(task.job))
if (!hasStream) {
return (
<div className="vv-copy-box vv-copy-loading">
@@ -1605,6 +1734,30 @@ const ViralVideoPage: React.FC = () => {
{sh.time_range}
</strong>
)}
{sh.speaker && (
<span
className="vv-sb-speaker-tag"
style={{
display: "inline-block",
padding: "2px 8px",
marginRight: 8,
marginLeft: 8,
borderRadius: 4,
fontSize: 12,
fontWeight: 500,
backgroundColor: ["店主", "主播", "老板", "我", "主讲人"].includes(
sh.speaker,
)
? "#e6f7ff"
: "#fff7e6",
color: ["店主", "主播", "老板", "我", "主讲人"].includes(sh.speaker)
? "#1890ff"
: "#fa8c16",
}}
>
{sh.speaker}
</span>
)}
<p className="vv-sb-field">
<strong className="vv-sb-field-k">景别/角度与运镜:</strong>
{editingField === shotKey("shot_type_angle_movement") ? (
@@ -1879,7 +2032,7 @@ const ViralVideoPage: React.FC = () => {
if (!locked) setEditingField("voiceover_script")
}}
>
{sb.voiceover_script}
{renderVoiceoverWithSpeakers(sb.voiceover_script)}
</span>
)}
</p>
@@ -2498,20 +2651,7 @@ const ViralVideoPage: React.FC = () => {
{/* 文案结果区(生成中/已生成) */}
{renderCopyResult()}
{/* 失败提示 */}
{task.uiStep === "failed" && task.copyError && (
<div className="vv-error">
<WarningFilled style={{ marginRight: 6 }} />
文案生成失败:{task.copyError}
<button
className="vv-btn vv-btn-warn vv-btn-sm"
style={{ marginLeft: 10 }}
onClick={handleRetry}
>
<ReloadOutlined /> 重试
</button>
</div>
)}
{/* 失败提示统一在页面底部展示,文案区不再单独显示(避免双块串台)*/}
</div>
{/* /.vv-scroll-inner */}
{/* STEP2 主按钮:✍️ 生成文案(文案未确认前显示) */}
@@ -2687,9 +2827,9 @@ const ViralVideoPage: React.FC = () => {
<br />
预计 1-3 分钟,请勿关闭页面
</div>
{task.job?.progress_message && (
{getJobPhaseMessage(task.job) && (
<div className="vv-muted" style={{ marginTop: 6, fontSize: 12 }}>
{task.job.progress_message}
{getJobPhaseMessage(task.job)}
</div>
)}
</div>
@@ -2708,11 +2848,11 @@ const ViralVideoPage: React.FC = () => {
</div>
</div>
{/* 错误 */}
{task.uiStep === "failed" && errMsg && (
{/* 错误(统一块,根据失败阶段显示正确前缀)*/}
{task.uiStep === "failed" && activeError && (
<div className="vv-error">
<WarningFilled style={{ marginRight: 6 }} />
视频生成失败:{errMsg}
{errLabel}:{activeError.msg}
<button
className="vv-btn vv-btn-warn vv-btn-sm"
style={{ marginLeft: 10 }}
@@ -2771,6 +2911,21 @@ const ViralVideoPage: React.FC = () => {
setAssetPicker((p) => ({ ...p, open: false }))
}}
/>
{task.marketingPurpose && task.marketingPurpose.includes("短剧") && (
<div
style={{
padding: "8px 12px",
marginBottom: 8,
backgroundColor: "#fff7e6",
border: "1px solid #ffd591",
borderRadius: 4,
fontSize: 13,
color: "#d46b08",
}}
>
💡 短剧模式将自动为对手戏角色分配配角音色
</div>
)}
<PresetVoicePickerModal
open={voicePickerOpen}
voices={presetVoices}
@@ -1,6 +1,11 @@
import { useCallback, useEffect, useRef } from "react"
import { getViralVideoJob } from "@/api/viral-video"
import { isAnalysisStage, type ViralVideoJob, type ViralVideoStatus } from "@/api/viral-video/types"
import {
isAnalysisStage,
getJobStage,
type ViralVideoJob,
type ViralVideoStatus,
} from "@/api/viral-video/types"
const TERMINAL: ViralVideoStatus[] = ["completed", "failed", "cancelled"]
@@ -44,14 +49,21 @@ export function useViralVideoPolling(
}
if (stoppedRef.current) return
// 视频渲染阶段(Seedance 多段视频生成较慢)拉长轮询间隔
const inRender = job.progress_stage === "rendering"
const stage = getJobStage(job)
const inRender = stage === "rendering"
// 分析阶段走默认间隔即可
const isAnalyzing = isAnalysisStage(job.progress_stage)
const isAnalyzing = isAnalysisStage(stage)
const nextDelay = inRender ? 3000 : isAnalyzing ? 2000 : intervalMs
timerRef.current = setTimeout(() => pollOnce(id), nextDelay)
} catch (_err) {
failCountRef.current += 1
if (stoppedRef.current) return
// P2-5: 连续失败 20 次(约 2 分钟)后熔断,避免后端挂掉时前端无限轮询
if (failCountRef.current >= 20) {
console.warn("[viral-video] 轮询连续失败 20 次,停止轮询,请刷新页面重试")
stop()
return
}
const delay = Math.min(intervalMs * 2 ** Math.min(failCountRef.current, 3), 10000)
timerRef.current = setTimeout(() => pollOnce(id), delay)
}
@@ -17,6 +17,11 @@ export interface ViralVideoWSError {
message: string
}
export interface ViralVideoTerminalEvent {
type: "viral_video:completed" | "viral_video:failed" | "viral_video:copy_generated"
job_id: string
}
export interface UseViralVideoWSOptions {
/** delta 事件回调(script_delta 推送时触发) */
onDelta?: (ev: ViralVideoDeltaEvent) => void
@@ -24,6 +29,8 @@ export interface UseViralVideoWSOptions {
onError?: (err: ViralVideoWSError) => void
/** 连接建立回调 */
onOpen?: () => void
/** P2-6: 收到终态事件(copy_generated/completed/failed)时回调,上层应立即主动拉取一次最新 job,减少终态延迟 */
onTerminal?: (ev: ViralVideoTerminalEvent) => void
}
const WS_SCHEME =
@@ -43,16 +50,18 @@ function buildWsUrl(jobId: string): string {
*/
export function useViralVideoWS(
jobId: string | null | undefined,
{ onDelta, onError, onOpen }: UseViralVideoWSOptions = {},
{ onDelta, onError, onOpen, onTerminal }: UseViralVideoWSOptions = {},
) {
const wsRef = useRef<WebSocket | null>(null)
const manualCloseRef = useRef(false)
const onDeltaRef = useRef(onDelta)
const onErrorRef = useRef(onError)
const onOpenRef = useRef(onOpen)
const onTerminalRef = useRef<UseViralVideoWSOptions["onTerminal"]>()
onDeltaRef.current = onDelta
onErrorRef.current = onError
onOpenRef.current = onOpen
onTerminalRef.current = onTerminal
const close = useCallback(() => {
manualCloseRef.current = true
@@ -95,9 +104,15 @@ export function useViralVideoWS(
const payload = JSON.parse(ev.data)
if (payload?.type === "viral_video:script_delta" && payload.data) {
onDeltaRef.current?.(payload as ViralVideoDeltaEvent)
} else if (
payload?.type === "viral_video:completed" ||
payload?.type === "viral_video:failed" ||
payload?.type === "viral_video:copy_generated"
) {
// P2-6: 收到终态事件时主动通知上层立即拉取,降低终态延迟(不用等下一个轮询周期)
onTerminalRef.current?.(payload as ViralVideoTerminalEvent)
}
// copy_generated/completed/failed 等终态事件由 HTTP 轮询统一处理,
// 此处仅消费 delta 做流式预览,不重复推状态。
// 心跳/其他事件忽略
} catch {
// 心跳/非 JSON 消息忽略
}
+182 -29
View File
@@ -355,10 +355,44 @@ def _vision_fallback(idx: int, reason: str, extra: dict | None = None) -> dict:
return d
def _refresh_oss_signed_url(raw: str) -> str:
"""把我们自己 OSS 的 URL 重新签新鲜签名(默认2小时),避免前端上传时签的1h URL
在阶段3被Wan/Seedance下载时过期(用户在文案页停留超过1小时导致Failed to download)。
- 我们 OSS 域名的URL:提取storage_key,走get_download_url重签
- 外链(公网资源、Ark/Seedream t2i产物等):原样返回
- storage_key(无scheme):走get_download_url签公网URL
"""
if not raw or not isinstance(raw, str):
return raw
s = raw.strip()
if not s:
return s
try:
from packages.shared.storage import get_storage_service
svc = get_storage_service()
bucket = getattr(svc, "bucket_name", "") or ""
if s.startswith("http://") or s.startswith("https://"):
from urllib.parse import urlparse
parsed = urlparse(s)
host = (parsed.hostname or "").lower()
is_our_oss = bool(bucket) and host.endswith(".aliyuncs.com") and host.startswith(f"{bucket}.")
if is_our_oss:
return svc.get_download_url(s, expires_seconds=7200)
return s # 外链原样返回
return svc.get_download_url(s.lstrip("/"), expires_seconds=7200)
except Exception as _e:
logger.warning("[爆款视频] URL重签失败回退原值: %s err=%s", s[:80], _e)
return s
def _normalize_image_url(raw: str, idx: int) -> str:
"""将 job.images 中的 storage_key/相对路径/空值统一归一化为可公网访问 URL。
- http(s):// → 直接用
- 其他 → storage_key,通过 SharedStorageService.get_url() 转公网 URL
- OSS URL(含前端上传的签名URL):统一通过 _refresh_oss_signed_url 重签2h,
避免用户在文案页停留超过1小时导致阶段3 Wan/Seedance 下载时签名过期
- 外链(Ark/Seedream t2i产物、公网资源):原样返回
- storage_key:签新鲜公网URL
- 空值/非字符串 → 抛 ValueError
"""
if not raw or not isinstance(raw, str):
@@ -366,17 +400,14 @@ def _normalize_image_url(raw: str, idx: int) -> str:
url = raw.strip()
if not url:
raise ValueError(f"图片 #{idx} URL 为空白字符串")
if url.startswith("http://") or url.startswith("https://"):
return url
storage_key = url.lstrip("/")
try:
from packages.shared.storage import get_storage_service
url = get_storage_service().get_url(storage_key)
except Exception as _e:
raise ValueError(f"图片 #{idx} storage_key={storage_key!r} 转公网URL失败: {_e}") from _e
logger.info("[爆款视频] 图片 #%d storage_key → 公网URL: %s", idx, url[:120])
return url
signed = _refresh_oss_signed_url(url)
if not signed:
raise ValueError(f"图片 #{idx} URL={url[:100]!r} 归一化失败")
if signed != url and (url.startswith("http://") or url.startswith("https://")):
logger.info("[爆款视频] 图片 #%d OSS URL 重签2h: %s", idx, signed[:120])
elif not url.startswith("http"):
logger.info("[爆款视频] 图片 #%d storage_key → 签名URL(2h): %s", idx, signed[:120])
return signed
# ── v8 图片分析结构归一化(老数据兼容只在这里做一次)────────────────────
@@ -461,7 +492,9 @@ def _step_video_analysis(job: ViralVideoJob) -> dict | None:
try:
from viral_video.video_analyzer import analyze_video_style
style_guide = analyze_video_style(job.reference_video_url)
# 参考视频URL重签(同样防止上传后停留过久签名过期)
video_url = _refresh_oss_signed_url(job.reference_video_url)
style_guide = analyze_video_style(video_url)
return style_guide if isinstance(style_guide, dict) else None
except ImportError as e:
logger.info("[爆款视频] video_analyzer 模块未就绪(%s),使用占位风格分析", e)
@@ -525,6 +558,67 @@ def _viral_structure_hint(structure: str) -> str:
return "【爆款结构:未指定】自由组织,保证开头有钩子、中段有卖点、结尾有行动引导"
def _marketing_purpose_hint(mp: str) -> str:
"""根据营销目的提供创作指导 hint。
覆盖前端 20 个 PURPOSES,分 4 类指导:
- 短剧类:多角色对话,格式"角色:台词",禁止旁白,角色间镜头切换
- 口播类:第一人称对镜头说话,真人出镜感
- 门店类:店主或探店博主出镜讲解+场景展示
- 品牌类:主演出镜说话或角色对白,禁止上帝视角旁白
"""
mp = (mp or "").strip()
if not mp:
return ""
# 短剧类(多角色对话)
if any(k in mp for k in ["对话短剧", "反转短剧", "悬念短剧", "情绪短片"]):
return "【短剧模式】必须双/多角色对话格式,台词用'角色:xxx'格式,镜头在角色间切换,禁止第三人称旁白解说。"
# 口播类(第一人称对镜头说话)
if any(
k in mp
for k in ["口播带货", "促销转化", "功能演示", "痛点解决", "获客引流", "账号涨粉", "活动通知", "场景种草"]
):
return "【口播模式】第一人称对镜头说话,像真人出镜,有语气停顿和情绪,禁止第三人称旁白。"
# 门店类(店主/探店博主出镜)
if any(k in mp for k in ["门店发现", "到店实录", "招牌体验", "同城团购"]):
return "【门店模式】店主或探店博主出镜讲解+场景展示,第一人称或角色对白,禁止上帝视角旁白。"
# 品牌类(主演出镜或角色对白)
if any(k in mp for k in ["品牌主张", "品牌故事", "生活方式", "创意概念"]):
return "【品牌模式】主演出镜说话或角色对白,禁止上帝视角旁白,要有品牌调性和情感共鸣。"
# 未匹配的营销目的:通用 hint
return "【通用模式】避免上帝视角旁白,优先第一人称或角色对话。"
def _target_customer_hint(tc: str) -> str:
"""根据目标客户提供台词风格指导。"""
tc = (tc or "").strip()
if not tc:
return ""
# 年轻人
if any(k in tc for k in ["18-25", "年轻", "学生", "Z世代", "95后", "00后"]):
return "【目标年轻客群】台词要活泼、有梗、节奏快,可用网络流行语。"
# 中年人
if any(k in tc for k in ["30-45", "中年", "家庭", "宝妈", "职场"]):
return "【目标中年客群】台词要实用、有共鸣,强调性价比和品质。"
# 老年人
if any(k in tc for k in ["50+", "老年", "退休", "银发"]):
return "【目标老年客群】台词要清晰、慢节奏,强调健康和实惠。"
# 高端
if any(k in tc for k in ["高端", "商务", "精英", "白领"]):
return "【目标高端客群】台词要专业、有格调,强调品质和身份。"
return ""
def _language_hint(language: str) -> str:
"""根据 language 代码返回语言提示。"""
lang = (language or "zh-CN").strip().lower()
@@ -764,8 +858,9 @@ def _script_from_xml(raw: str, job: ViralVideoJob) -> dict | None:
ref_idx = xp.attr_int(ref_raw, -1) if ref_raw not in (None, "") else -1
if not isinstance(ref_idx, int) or ref_idx < 0:
ref_idx = None
speaker = xp.text_of(body, "speaker") or "主播"
if voice:
voice_parts.append(voice)
voice_parts.append(f"[speaker:{speaker}]{voice}")
shot = {
"time_range": a.get("time_range") or xp.text_of(body, "time_range") or f"{i * 3}-{(i + 1) * 3}秒",
"shot_type_angle_movement": visual or "中景平视,固定镜头",
@@ -1259,6 +1354,45 @@ def _resolve_tts_voice_id(job: ViralVideoJob) -> str:
return raw_voice_id or default_voice
def _parse_speaker_segments(text: str) -> list[tuple[str, str]]:
"""解析 voiceover_script 中的 [speaker:xxx] 标记,返回 [(speaker, text), ...] 列表。"""
import re
if not text:
return []
# 匹配 [speaker:xxx]text 格式
pattern = r"\[speaker:([^\]]+)\]([^\[]*)"
matches = re.findall(pattern, text)
if not matches:
# 没有 speaker 标记,返回单个默认角色
return [("主播", text)]
return [(speaker.strip(), seg_text.strip()) for speaker, seg_text in matches if seg_text.strip()]
def _get_speaker_voice_id(speaker: str, main_voice_id: str, is_main_voice_male: bool = True) -> str:
"""根据角色名分配合适的音色 ID。
主角(店主/主播/老板等)使用用户选择的音色,配角自动分配异性音色。
"""
# 主角列表
main_speakers = ["店主", "主播", "老板", "我", "主讲人", "店长"]
# 配角列表
sub_speakers = ["顾客", "客人", "朋友", "闺蜜", "路人", "店员"]
if speaker in main_speakers or not any(s in speaker for s in sub_speakers):
return main_voice_id
# 配角分配异性音色
if is_main_voice_male:
return "longxiaochun" # 女声
else:
return "longsanshu" # 男声
def _step_tts(job: ViralVideoJob, voiceover_script: str):
"""步骤 5: CosyVoice 整段配音 → 返回本地 MP3 Path;失败返回 None。
@@ -1728,11 +1862,13 @@ def _step_render(job: ViralVideoJob, copy_result: dict, tts_audio_url: str | Non
# reference_audios: TTS 音频驱动口型
ref_audios = [tts_audio_url] if tts_audio_url else []
# reference_images: 产品图(除首帧外的其他图作为多参考;首帧通过 image_url 传)
images = list(job.images or [])
# 阶段3进入时再次重签URL(用户可能在文案页停留超1h,阶段1签的URL已过期)
images = [_refresh_oss_signed_url(u) for u in (job.images or []) if u]
first_image = images[0] if images else None
rest_images = images[1:30] if len(images) > 1 else []
# reference_videos: 参考视频(可选)
ref_videos = [job.reference_video_url] if getattr(job, "reference_video_url", "") else []
# reference_videos: 参考视频(可选,也重签)
_ref_vid = _refresh_oss_signed_url(getattr(job, "reference_video_url", "") or "")
ref_videos = [_ref_vid] if _ref_vid else []
tmpdir = Path(tempfile.mkdtemp(prefix=f"viral_{job.id}_"))
logger.info(
@@ -1922,7 +2058,7 @@ def run_viral_video_pipeline(self: Task, job_id: str) -> dict:
job.mark_running()
_save_job(repo, job, session)
_hb_stop, _hb_thread = _start_heartbeat_thread(job_id)
_hb_stop, _ = _start_heartbeat_thread(job_id)
_set_stage(job, repo, session, ViralVideoStage.IMAGE_ANALYSIS, "正在分析商品特征...")
image_analysis = _step_image_analysis(job)
@@ -1972,8 +2108,16 @@ def run_viral_video_pipeline(self: Task, job_id: str) -> dict:
except Retry:
raise
except Exception as e:
logger.error("[爆款视频] 流水线异常: %s", e, exc_info=True)
_mark_failed_and_notify(job_id, session, None, None, str(e), "")
logger.error("[爆款视频][pipeline] 旧一键流水线失败 job_id=%s: %s", job_id, e, exc_info=True)
_err_stage = ""
try:
_r = SQLAlchemyViralVideoJobRepository(session)
_j = _r.get(job_id)
if _j is not None and getattr(_j, "current_stage", None):
_err_stage = _j.current_stage
except Exception:
pass
_mark_failed_and_notify(job_id, session, None, None, str(e), _err_stage)
return {"ok": False, "job_id": job_id, "error": str(e)}
finally:
if _hb_stop is not None:
@@ -1996,8 +2140,16 @@ def resume_viral_video_pipeline(self: Task, job_id: str) -> dict:
except Retry:
raise
except Exception as e:
logger.error("[爆款视频] 恢复流水线异常: %s", e, exc_info=True)
_mark_failed_and_notify(job_id, session, None, None, str(e), "")
logger.error("[爆款视频][resume-pipeline] 恢复流水线失败 job_id=%s: %s", job_id, e, exc_info=True)
_err_stage = ""
try:
_r = SQLAlchemyViralVideoJobRepository(session)
_j = _r.get(job_id)
if _j is not None and getattr(_j, "current_stage", None):
_err_stage = _j.current_stage
except Exception:
pass
_mark_failed_and_notify(job_id, session, None, None, str(e), _err_stage)
return {"ok": False, "job_id": job_id, "error": str(e)}
finally:
if session:
@@ -2033,13 +2185,14 @@ def run_video_style_analysis(self: Task, job_id: str) -> dict:
def _mark_failed_and_notify(job_id: str, session, repo, job, err_msg: str, stage: str = "") -> None:
"""标记任务失败并通知。若传入的 session 已失效(因前面异常导致 rollback 状态),
会自动 fallback 到新建 SessionLocal 重新标记,确保状态一定落库。"""
会自动 fallback 到新建 SessionLocal 重新标记,确保状态一定落库。
BUG 修复:失败时持久化 stage 到 current_stage,前端才能正确归因错误。"""
try:
# 尝试用传入的 session 标记
marked = False
if job is not None and not job.is_terminal and session is not None:
try:
job.mark_failed(err_msg)
job.mark_failed(err_msg, stage=stage)
_save_job(repo, job, session)
marked = True
except Exception as se:
@@ -2055,7 +2208,7 @@ def _mark_failed_and_notify(job_id: str, session, repo, job, err_msg: str, stage
r = SQLAlchemyViralVideoJobRepository(ssn)
j = r.get(job_id)
if j is not None and not j.is_terminal:
j.mark_failed(err_msg)
j.mark_failed(err_msg, stage=stage)
r.update(j)
ssn.commit()
finally:
@@ -2094,7 +2247,7 @@ def run_viral_video_analyze(self: Task, job_id: str) -> dict:
job.mark_running()
_save_job(repo, job, session)
_hb_stop, _hb_thread = _start_heartbeat_thread(job_id)
_hb_stop, _ = _start_heartbeat_thread(job_id)
_set_stage(job, repo, session, ViralVideoStage.IMAGE_ANALYSIS, "正在分析商品特征...")
image_analysis = _step_image_analysis(job)
@@ -2185,7 +2338,7 @@ def run_viral_video_generate_copy(self: Task, job_id: str) -> dict:
return {"ok": False, "error": f"unexpected status: {job.status}"}
job.touch_heartbeat()
_save_job(repo, job, session)
_hb_stop, _hb_thread = _start_heartbeat_thread(job_id)
_hb_stop, _ = _start_heartbeat_thread(job_id)
# v8:意图理解并入分镜生成,一次 LLM 调用;流式推送 script_delta 给前端
image_analysis = normalize_image_analysis(job.image_analysis)
@@ -2566,7 +2719,7 @@ def run_viral_video_render(self: Task, job_id: str) -> dict:
return {"ok": False, "error": f"unexpected status: {job.status}"}
job.touch_heartbeat()
_save_job(repo, job, session)
_hb_stop, _hb_thread = _start_heartbeat_thread(job_id)
_hb_stop, _ = _start_heartbeat_thread(job_id)
return _run_render_pipeline(job_id, session, repo, job)
except Retry:
raise
+11 -4
View File
@@ -211,6 +211,7 @@ class DittoEmotionService:
self.settings = settings or get_api_settings()
self._client = None
self._client_api_key: str | None = None
def _cfg(self, key: str) -> Any:
"""优先读后台 system_config,未配置则回退到 settings(env 默认)."""
@@ -236,10 +237,16 @@ class DittoEmotionService:
return hashlib.md5(text.strip().encode("utf-8")).hexdigest()
def _get_llm_client(self):
if self._client is None:
from packages.shared.ai_client import get_doubao_client
"""创建/复用 DoubaoClient;API Key 优先读后台配置(DB),fallback 环境变量。
self._client = get_doubao_client()
后台可能随时改 doubao_api_key,每次调用前对比 key,变化则重建 client。
"""
api_key = (self._cfg("doubao_api_key") or "").strip()
if self._client is None or self._client_api_key != api_key:
from packages.shared.ai_client import DoubaoClient
self._client = DoubaoClient(api_key=api_key)
self._client_api_key = api_key
return self._client
def _call_llm(self, text: str) -> list[EmotionSegment]:
@@ -309,7 +316,7 @@ def _cached_analyze(service: DittoEmotionService, cache_key: str, text: str) ->
# 如果 LLM 返回空(比如分句数量不匹配),尝试直接对预分句结果分析
if not segments:
pre_splits = split_sentences(text)
if len(pre_splits) > 1:
if len(pre_splits) >= 1:
# 用预分句结果兜底:全中性低强度
segments = [EmotionSegment(text=s, emo=EMO_NEUTRAL, intensity=0.1) for s in pre_splits]
return segments
+11 -1
View File
@@ -244,6 +244,13 @@ class ViralVideoJob:
self.heartbeat_at = _now
self.status = ViralVideoStatus.RUNNING
self.updated_at = _now
# 清空上一次渲染留下的错误/产物(参考 resume_from_image_analyzed 对齐)
self.error_msg = ""
self.result_video_url = ""
self.current_stage = ""
self.phase_message = ""
self.completed_at = None
self.credits_cost = 0.0
def resume_from_confirm(self) -> None:
if self.status != ViralVideoStatus.WAIT_USER_CONFIRM:
@@ -260,9 +267,12 @@ class ViralVideoJob:
self.completed_at = datetime.now(timezone.utc)
self.updated_at = datetime.now(timezone.utc)
def mark_failed(self, error_msg: str) -> None:
def mark_failed(self, error_msg: str, stage: str = "") -> None:
self.status = ViralVideoStatus.FAILED
self.error_msg = error_msg
# 失败时持久化失败阶段,避免前端错误归因
if stage:
self.current_stage = stage
self.completed_at = datetime.now(timezone.utc)
self.updated_at = datetime.now(timezone.utc)
+3 -1
View File
@@ -67,10 +67,12 @@ def _classify_dashscope_error(status_code: int, body: str, task_msg: str = "") -
return "invalid_param", f"Wan 3.0 参数错误:{msg_in_body or body[:200]}"
if status_code == 0:
return "network_error", "Wan 3.0 服务连接失败(网络超时),请稍后重试。"
# 任务内失败
# 任务内失败(异步轮询结果):此时 HTTP 200 只是查询成功,不代表任务成功,提示文案不要带 HTTP 200 以免误导
if task_msg and any(kw in task_msg.lower() for kw in ("portrait", "真人", "人脸", "violation", "blocked")):
return "portrait_intercept", "Wan 3.0 视频内容被安全策略拦截,请调整文案或参考图后重试。"
detail = msg_in_body or body[:200]
if task_msg and status_code == 200:
return "task_failed", f"Wan 3.0 视频生成失败:{detail}"
return "unknown", f"Wan 3.0 视频生成失败(HTTP {status_code}):{detail}"
+16 -1
View File
@@ -10,7 +10,22 @@ source "${SCRIPT_DIR}/ci_env.sh"
echo "=== Installing mypy ==="
python3 -m pip install -q mypy
# pip�容错: 默认�(阿里云)缺文件时fallback到清�/官方�(2026-10-10 librt-0.6.0 metadata 404)
MYPY_SPEC="mypy<1.19"
INSTALL_OK=0
python3 -m pip install -q "$MYPY_SPEC" && INSTALL_OK=1 || true
if [ "$INSTALL_OK" != "1" ]; then
echo "WARN: default pip index failed, retry tsinghua mirror..."
python3 -m pip install -q -i https://pypi.tuna.tsinghua.edu.cn/simple "$MYPY_SPEC" && INSTALL_OK=1 || true
fi
if [ "$INSTALL_OK" != "1" ]; then
echo "WARN: tsinghua mirror failed, retry pypi.org..."
python3 -m pip install -q -i https://pypi.org/simple "$MYPY_SPEC" && INSTALL_OK=1 || true
fi
if [ "$INSTALL_OK" != "1" ]; then
echo "ERROR: pip install mypy failed on all indexes"
exit 1
fi
mypy --version
echo ""
echo "=== Running mypy type check (hard gate mode) ==="
+4 -2
View File
@@ -108,8 +108,10 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_request_buffering off;
}
+57
View File
@@ -223,3 +223,60 @@ class TestPromptLoading:
custom = "分析情绪: {文案}"
svc = _make_service(enabled=True, prompt=custom)
assert svc._get_prompt_template() == custom
# ── _get_llm_client:DB 配置 api_key 优先 + 变化重建 ─────────────
class TestGetLLMClient:
def test_uses_config_api_key(self):
svc = _make_service(enabled=True)
with patch.object(svc, "_cfg", return_value="sk-from-db") as mock_cfg:
with patch("packages.shared.ai_client.DoubaoClient") as MockClient:
svc._get_llm_client()
mock_cfg.assert_called_with("doubao_api_key")
assert MockClient.call_args.kwargs["api_key"] == "sk-from-db"
def test_rebuilds_client_when_key_changes(self):
svc = _make_service(enabled=True)
keys = iter(["sk-key-v1", "sk-key-v2"])
with patch.object(svc, "_cfg", side_effect=lambda k: next(keys)):
with patch("packages.shared.ai_client.DoubaoClient") as MockClient:
MockClient.side_effect = lambda **kw: MagicMock(api_key=kw["api_key"])
c1 = svc._get_llm_client()
c2 = svc._get_llm_client()
assert c1 is not c2
assert MockClient.call_count == 2
def test_reuses_client_when_key_unchanged(self):
svc = _make_service(enabled=True)
with patch.object(svc, "_cfg", return_value="sk-same"):
with patch("packages.shared.ai_client.DoubaoClient") as MockClient:
MockClient.side_effect = lambda **kw: MagicMock(api_key=kw["api_key"])
c1 = svc._get_llm_client()
c2 = svc._get_llm_client()
assert c1 is c2
assert MockClient.call_count == 1
def test_empty_key_falls_back_to_doubao_client_default(self):
"""DB/env 都没配时传空串,由 DoubaoClient 内部 fallback env / 标记不可用."""
svc = _make_service(enabled=True)
with patch.object(svc, "_cfg", return_value=""):
with patch("packages.shared.ai_client.DoubaoClient") as MockClient:
svc._get_llm_client()
assert MockClient.call_args.kwargs["api_key"] == ""
# ── 单句兜底:LLM 返回空时单句也走中性兜底(>= 1)────────────────
class TestSingleSentenceFallback:
def test_single_sentence_gets_neutral_fallback(self):
import packages.application.ditto_emotion_service as m
svc = _make_service(enabled=True)
m._cached_analyze.cache_clear()
try:
with patch.object(svc, "_call_llm", return_value=[]):
segs = svc.analyze("独一无二单句兜底测试文案abc123")
assert len(segs) == 1
assert segs[0].emo == EMO_NEUTRAL
assert segs[0].intensity == 0.1
finally:
m._cached_analyze.cache_clear()
+90
View File
@@ -6,6 +6,8 @@ Ditto 单例 reset 联动、PUT 校验。
from __future__ import annotations
from unittest.mock import MagicMock
import pytest
from sqlalchemy import create_engine, event
from sqlalchemy.orm import sessionmaker
@@ -285,3 +287,91 @@ class TestAdminRouteValidation:
with pytest.raises(ValueError):
route._validate_value("ditto_emotion_enabled", "yes")
assert route._validate_value("ditto_emotion_enabled", True) is True
def test_validate_api_key(self):
route = self._route()
with pytest.raises(ValueError):
route._validate_value("doubao_api_key", " ")
with pytest.raises(ValueError):
route._validate_value("doubao_api_key", 123)
assert route._validate_value("doubao_api_key", "sk-abc123") == "sk-abc123"
def test_whitelist_contains_api_key(self):
route = self._route()
assert "doubao_api_key" in route._WHITELIST
assert "doubao_api_key" in route._DESCRIPTIONS
class TestAdminRouteSecretMasking:
"""doubao_api_key GET 脱敏 + PUT 响应脱敏."""
def _route(self):
from apps.api.app.api.routes.admin import ditto_emotion as route
return route
def _mock_service(self, values):
svc = MagicMock()
svc.get_config = lambda key, default=None: values.get(key, default)
return svc
def test_get_config_masks_db_configured_key(self, monkeypatch):
route = self._route()
monkeypatch.setattr(
route,
"get_system_config_service",
lambda: self._mock_service({"doubao_api_key": "sk-real-secret-key"}),
)
monkeypatch.setattr(route, "_settings", lambda: MagicMock(doubao_api_key=""))
item = route._build_config_item("doubao_api_key")
assert item["value"] == route._SECRET_PLACEHOLDER
assert item["default"] == ""
assert "sk-real-secret-key" not in str(item)
def test_get_config_masks_env_configured_key(self, monkeypatch):
route = self._route()
monkeypatch.setattr(
route,
"get_system_config_service",
lambda: self._mock_service({}),
)
monkeypatch.setattr(route, "_settings", lambda: MagicMock(doubao_api_key="sk-env-key"))
item = route._build_config_item("doubao_api_key")
assert item["value"] == route._SECRET_PLACEHOLDER
assert "sk-env-key" not in str(item)
def test_get_config_empty_when_unconfigured(self, monkeypatch):
route = self._route()
monkeypatch.setattr(
route,
"get_system_config_service",
lambda: self._mock_service({}),
)
monkeypatch.setattr(route, "_settings", lambda: MagicMock(doubao_api_key=""))
item = route._build_config_item("doubao_api_key")
assert item["value"] == ""
def test_get_config_never_leaks_plaintext(self, monkeypatch):
route = self._route()
secret = "sk-top-secret-12345"
monkeypatch.setattr(
route,
"get_system_config_service",
lambda: self._mock_service({"doubao_api_key": secret}),
)
monkeypatch.setattr(route, "_settings", lambda: MagicMock(doubao_api_key=secret))
result = route.get_config()
assert secret not in str(result)
def test_put_response_masks_secret(self, monkeypatch):
route = self._route()
svc = self._mock_service({})
svc.set_config = MagicMock(return_value="sk-new-key")
monkeypatch.setattr(route, "get_system_config_service", lambda: svc)
payload = route.ConfigUpdatePayload(configs={"doubao_api_key": "sk-new-key"})
result = route.update_config(payload, x_api_key="test-key")
assert result["ok"] is True
assert result["updated"]["doubao_api_key"] == route._SECRET_PLACEHOLDER
assert "sk-new-key" not in str(result)
# 落库值必须是明文(服务要用),只有响应脱敏
assert svc.set_config.call_args[0][1] == "sk-new-key"
+2 -2
View File
@@ -400,7 +400,7 @@ class TestMarkFailedAndNotifySessionFallback:
job.mark_failed.assert_called()
# fallback路径:新session上repo.get(job-1)被调用,且新job被mark_failed并commit
fake_repo.get.assert_called_with("job-1")
fake_job_in_db.mark_failed.assert_called_with("boom")
fake_job_in_db.mark_failed.assert_called_with("boom", stage="render")
fake_repo.update.assert_called_with(fake_job_in_db)
fake_ssn.commit.assert_called()
fake_ssn.close.assert_called()
@@ -419,7 +419,7 @@ class TestMarkFailedAndNotifySessionFallback:
with patch.object(vv, "_emit_progress") as mock_emit:
# 不mock SessionLocal,如果fallback被错误触发会抛AttributeError
vv._mark_failed_and_notify("job-2", session, repo, job, "err", stage="copy")
job.mark_failed.assert_called_with("err")
job.mark_failed.assert_called_with("err", stage="copy")
mock_save.assert_called()
mock_emit.assert_called_once()
+1 -1
View File
@@ -144,7 +144,7 @@ class TestRetryViralVideo:
assert job.status == ViralVideoStatus.PENDING
assert job.retry_count == 2
mock_send.assert_called_once_with("worker.run_viral_video_pipeline", args=["job-retry"])
mock_send.assert_called_once_with("worker.run_viral_video_analyze", args=["job-retry"])
assert resp.id == "job-retry"
def test_retry_without_body_keeps_original_params(self):