fix: 统一AI生成失败提示
This commit is contained in:
@@ -14,7 +14,7 @@ SSE 事件(每帧 `data: {json}\n\n`,json 带 type):
|
||||
saved {script_version_id, version} —— 已落库的 ScriptVersion(含 segments/metadata)
|
||||
summary {text} —— 模型自己写的收尾交付语(当 AI 回复气泡,替代写死的「已生成」)
|
||||
done {} —— 结束
|
||||
error {detail} —— 失败(已回滚额度)
|
||||
error {detail,error} —— 失败(已回滚额度;error 为安全业务错误对象)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -26,6 +26,7 @@ from pathlib import Path
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
|
||||
from apps.ai.generation_errors import classify_generation_error
|
||||
from apps.ai.models import AITask, ModelConfig
|
||||
from apps.billing.services.ledger import charge_reserved_credit, release_credit
|
||||
|
||||
@@ -621,7 +622,8 @@ def stream_script_agent(
|
||||
},
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001 — 多为额度不足
|
||||
yield _sse({"type": "error", "detail": f"任务创建失败(可能额度不足):{exc}"})
|
||||
internal_kind = "user_credit_insufficient" if str(exc).strip().lower() == "insufficient credit" else ""
|
||||
yield _sse(_script_error_event(exc, internal_kind=internal_kind))
|
||||
return
|
||||
reservation = task.credit_reservation
|
||||
# 额度是否已结算(charge 成功 / release 失败)。客户端中途断连时,生成器被 .close() 抛
|
||||
@@ -676,7 +678,7 @@ def stream_script_agent(
|
||||
_fail_task(task, reservation, str(exc))
|
||||
settled = True
|
||||
yield _sse({"type": "tool", "id": "generate", "status": "error"})
|
||||
yield _sse({"type": "error", "detail": f"脚本生成失败:{exc}"})
|
||||
yield _sse(_script_error_event(exc, reference_id=str(task.id)))
|
||||
return
|
||||
|
||||
yield _sse({"type": "tool", "id": "generate", "status": "done"})
|
||||
@@ -707,7 +709,7 @@ def stream_script_agent(
|
||||
except Exception as exc: # noqa: BLE001 — 落库失败:atomic 已回滚 charge,补释放预留
|
||||
_fail_task(task, reservation, f"保存脚本失败:{exc}")
|
||||
settled = True
|
||||
yield _sse({"type": "error", "detail": f"保存脚本失败:{exc}"})
|
||||
yield _sse(_script_error_event(exc, reference_id=str(task.id), internal_kind="processing_failed"))
|
||||
return
|
||||
|
||||
from apps.projects.serializers import ScriptVersionSerializer
|
||||
@@ -743,6 +745,26 @@ def _fail_task(task, reservation, message: str) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def _script_error_event(
|
||||
exc: Exception,
|
||||
*,
|
||||
reference_id: str | None = None,
|
||||
internal_kind: str = "",
|
||||
) -> dict:
|
||||
"""脚本 SSE 的安全失败帧;原始异常只落任务记录/日志,不回传普通用户。"""
|
||||
public_error = classify_generation_error(
|
||||
exc,
|
||||
operation="script_generate",
|
||||
internal_kind=internal_kind,
|
||||
reference_id=reference_id,
|
||||
)
|
||||
return {
|
||||
"type": "error",
|
||||
"detail": public_error.fallback_message,
|
||||
"error": public_error.as_dict(),
|
||||
}
|
||||
|
||||
|
||||
def _load_base_draft(project, base_version_id: str) -> dict | None:
|
||||
from apps.projects.models import ScriptVersion
|
||||
|
||||
|
||||
Reference in New Issue
Block a user