feat(core): 脚本 agent 真流式思考动画 + 场景图16:9 + 资产卡/审核标修复 + 模型收敛

- 进度区改竖线时间轴:推理模型 reasoning_content 逐字转发(volcano),状态字=模型实时最新一句+秒数+折叠展开思考全文(替代旧 ProgressStream/ThinkingStream)
- 场景基础资产出图改 16:9(run_base_asset_task size + 提取提示词横屏)
- 已出图立绘主卡不再被在途轮询任务误盖转圈
- 审核态随项目详情持久下发(BaseAssetGroup.adopted_asset_review),刷新不丢徽章
- 设定卡加「← 返回」回三选项;模型选择器固定按 created_at 排序(默认豆包2.0Pro)
- 新增 reasoning 转发回归测试

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-18 11:25:13 +08:00
co-authored by Claude Opus 4.8
parent 675b4db0aa
commit 4c21d85ba1
9 changed files with 201 additions and 50 deletions
+47
View File
@@ -142,6 +142,7 @@ from unittest.mock import patch
from django.test import TestCase
from apps.accounts.models import Team, User
from apps.ai.providers.volcano import VolcanoArkProvider
from apps.ai.services import enqueue_standalone_images
from apps.assets.models import Asset, AssetFile
from apps.billing.models import CreditAccount
@@ -209,3 +210,49 @@ class StandaloneImageReferenceTests(TestCase):
enqueue_standalone_images(team=self.team, user=self.user, prompt="平台套图", mode="cover", count=1, product_id=str(self.product.id), ratio="4:5")
prov.image_generation.assert_called_once()
prov.image_edit.assert_not_called()
class _FakeStreamResp:
"""模拟 requests 流式响应:支持 with、raise_for_status、可写 encoding、iter_lines。"""
status_code = 200
encoding = None
def __init__(self, lines):
self._lines = lines
def __enter__(self):
return self
def __exit__(self, *exc):
return False
def raise_for_status(self):
return None
def iter_lines(self, decode_unicode=True): # noqa: ARG002
yield from self._lines
class ChatStreamReasoningTests(SimpleTestCase):
"""推理模型(豆包 seed-pro 等)思考期只发 reasoning_content、不发 content。
provider 必须把它作为独立 `reasoning` 事件转发——否则脚本 agent 思考期零输出 =
前端「卡在生成分镜」假死。本测试锁住该转发,防回归。"""
def test_reasoning_content_forwarded_as_reasoning_event(self):
def _chunk(delta):
return "data: " + json.dumps({"choices": [{"delta": delta}]}, ensure_ascii=False)
lines = [
_chunk({"reasoning_content": "先想想"}),
_chunk({"reasoning_content": "用户要4镜"}),
_chunk({"content": "正在生成"}),
_chunk({"content": "脚本…"}),
"data: [DONE]",
]
prov = VolcanoArkProvider(api_key="k", base_url="http://x")
with patch("apps.ai.providers.volcano.requests.post", return_value=_FakeStreamResp(lines)):
events = list(prov.chat_completion_stream(model="m", messages=[{"role": "user", "content": "hi"}]))
self.assertEqual([e["type"] for e in events], ["reasoning", "reasoning", "delta", "delta", "done"])
self.assertEqual([e["text"] for e in events if e["type"] == "reasoning"], ["先想想", "用户要4镜"])
self.assertEqual("".join(e["text"] for e in events if e["type"] == "delta"), "正在生成脚本…")