fix(chat): always prepend image model badge in result message
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-02-21 04:30:23 +08:00
parent 75e139c167
commit 9e69e9e1fe

View File

@ -1437,6 +1437,34 @@ async function normalizeAssistantImageMarkdown(
return normalizedText;
}
function prependImageModelBadge(text: string, modelDisplayName?: string | null): string {
const normalizedText = String(text || "").trim();
if (!normalizedText) return normalizedText;
const normalizedModelName = String(modelDisplayName || "").trim();
if (!normalizedModelName) return normalizedText;
if (
/^\s*[◈◇◆🔹⬡✦•·]\s*[^\n]+/im.test(normalizedText) ||
/^\s*(?:Routed to|Using model|使用模型|模型)\s*[::]/im.test(normalizedText)
) {
return normalizedText;
}
return `◈ ${normalizedModelName}\n\n${normalizedText}`;
}
function resolveModelDisplayNameByModelId(
models: Awaited<ReturnType<typeof getEnabledAiModelsWithProvider>> | undefined,
modelId: string | undefined,
): string {
if (!modelId || !models?.length) return "";
const match = models.find(
(item) => item.model.modelId === modelId || item.model.id === modelId,
);
return String(match?.model?.displayName || "");
}
/**
* 解析生图 Markdown 并保存图片记录到数据库
* 支持三种格式:thumb|||url|||size、thumb$$url$$size、thumb|url|size
@ -2969,6 +2997,15 @@ export async function POST(request: Request) {
console.log("[Chat API] Gemini generated, length:", imageMarkdown.length);
console.log("[Chat API] Gemini image markdown:", imageMarkdown.substring(0, 200));
console.log("[Chat API] Used model ID:", usedModelId);
const usedModelDisplayName =
resolveModelDisplayNameByModelId(allModels, usedModelId) ||
currentModelConfig?.displayName ||
actualModelId;
const imageMarkdownWithModel = prependImageModelBadge(
imageMarkdown,
usedModelDisplayName,
);
// 生成一个统一的消息 ID
const messageId = generateUUID();
@ -2976,7 +3013,7 @@ export async function POST(request: Request) {
// 写入消息到流 - 使用正确的 parts 格式
writeAssistantTextChunk(
writer,
imageMarkdown,
imageMarkdownWithModel,
"gemini:image-result",
messageId,
);
@ -2996,7 +3033,7 @@ export async function POST(request: Request) {
id: messageId,
chatId: id,
role: "assistant",
parts: [{ type: "text", text: imageMarkdown }],
parts: [{ type: "text", text: imageMarkdownWithModel }],
attachments: [], // 必须提供 attachments 字段(数据库 notNull)
createdAt: new Date(),
videoStorageStatus: null,
@ -3015,7 +3052,7 @@ export async function POST(request: Request) {
// 保存图片记录到 GeneratedImage 表
await saveGeneratedImages(
imageMarkdown,
imageMarkdownWithModel,
session.user.id,
id,
messageId,
@ -3068,6 +3105,10 @@ export async function POST(request: Request) {
});
const imageMarkdown = volcanoResult.text || "图片生成失败";
const imageMarkdownWithModel = prependImageModelBadge(
imageMarkdown,
volcanoModel.model.displayName || volcanoModel.model.modelId,
);
console.log("[Chat API] Volcano Vision failover success, length:", imageMarkdown.length);
// 生成消息 ID
@ -3076,7 +3117,7 @@ export async function POST(request: Request) {
// 写入消息到流
writeAssistantTextChunk(
writer,
imageMarkdown,
imageMarkdownWithModel,
"gemini:volcano-failover-result",
messageId,
);
@ -3096,7 +3137,7 @@ export async function POST(request: Request) {
id: messageId,
chatId: id,
role: "assistant",
parts: [{ type: "text", text: imageMarkdown }],
parts: [{ type: "text", text: imageMarkdownWithModel }],
attachments: [],
createdAt: new Date(),
videoStorageStatus: null,
@ -3115,7 +3156,7 @@ export async function POST(request: Request) {
// 保存图片记录到 GeneratedImage 表
await saveGeneratedImages(
imageMarkdown,
imageMarkdownWithModel,
session.user.id,
id,
messageId,
@ -3415,6 +3456,15 @@ export async function POST(request: Request) {
console.log("[Chat API] Alibaba generated, length:", imageMarkdown.length);
console.log("[Chat API] Alibaba used model:", usedModelId);
const usedModelDisplayName =
resolveModelDisplayNameByModelId(allModels, usedModelId) ||
alibabaModelConfig?.displayName ||
actualModelId;
const imageMarkdownWithModel = prependImageModelBadge(
imageMarkdown,
usedModelDisplayName,
);
// 生成消息 ID(图片消息)
const messageId = generateUUID();
@ -3422,7 +3472,7 @@ export async function POST(request: Request) {
// 写入图片消息到流
writeAssistantTextChunk(
writer,
imageMarkdown,
imageMarkdownWithModel,
"alibaba:image-result",
messageId,
);
@ -3442,7 +3492,7 @@ export async function POST(request: Request) {
id: messageId,
chatId: id,
role: "assistant",
parts: [{ type: "text", text: imageMarkdown }],
parts: [{ type: "text", text: imageMarkdownWithModel }],
attachments: [],
createdAt: new Date(),
videoStorageStatus: null,
@ -3460,7 +3510,7 @@ export async function POST(request: Request) {
// 保存图片记录到 GeneratedImage 表
await saveGeneratedImages(
imageMarkdown,
imageMarkdownWithModel,
session.user.id,
id,
messageId,
@ -3747,6 +3797,15 @@ export async function POST(request: Request) {
}
console.log("[Chat API] Volcano Vision generated, length:", imageMarkdown.length);
console.log("[Chat API] Volcano Vision image markdown:", imageMarkdown.substring(0, 200));
const usedModelDisplayName =
resolveModelDisplayNameByModelId(allModels, usedModelId) ||
volcanoModelConfig?.displayName ||
actualModelId;
const imageMarkdownWithModel = prependImageModelBadge(
imageMarkdown,
usedModelDisplayName,
);
// 生成消息 ID(图片消息)
const messageId = generateUUID();
@ -3754,7 +3813,7 @@ export async function POST(request: Request) {
// 写入图片消息到流
writeAssistantTextChunk(
writer,
imageMarkdown,
imageMarkdownWithModel,
"volcano:image-result",
messageId,
);
@ -3774,7 +3833,7 @@ export async function POST(request: Request) {
id: messageId,
chatId: id,
role: "assistant",
parts: [{ type: "text", text: imageMarkdown }],
parts: [{ type: "text", text: imageMarkdownWithModel }],
attachments: [], // 必须提供 attachments 字段(数据库 notNull)
createdAt: new Date(),
videoStorageStatus: null,
@ -3793,7 +3852,7 @@ export async function POST(request: Request) {
// 保存图片记录到 GeneratedImage 表
await saveGeneratedImages(
imageMarkdown,
imageMarkdownWithModel,
session.user.id,
id,
messageId,
@ -4096,6 +4155,10 @@ export async function POST(request: Request) {
rawText,
effectiveImageParams?.imageSize || "2K"
);
const normalizedTextWithModel = prependImageModelBadge(
normalizedText,
currentModelConfig?.displayName || actualModelId,
);
const messageId = generateUUID();
dataStream.write({
@ -4103,7 +4166,7 @@ export async function POST(request: Request) {
data: JSON.stringify({
id: messageId,
role: "assistant",
parts: [{ type: "text", text: normalizedText }],
parts: [{ type: "text", text: normalizedTextWithModel }],
}),
});
@ -4122,7 +4185,7 @@ export async function POST(request: Request) {
{
id: messageId,
role: "assistant",
parts: [{ type: "text", text: normalizedText }],
parts: [{ type: "text", text: normalizedTextWithModel }],
createdAt: new Date(),
attachments: [],
chatId: id,
@ -4141,7 +4204,7 @@ export async function POST(request: Request) {
(p): p is { type: "text"; text: string } => p.type === "text"
)?.text || "";
await saveGeneratedImages(
normalizedText,
normalizedTextWithModel,
session.user.id,
id,
messageId,