diff --git a/components/canvas/CanvasChatPanel.tsx b/components/canvas/CanvasChatPanel.tsx
index fa9e17aa2..1e0fd3568 100644
--- a/components/canvas/CanvasChatPanel.tsx
+++ b/components/canvas/CanvasChatPanel.tsx
@@ -5,7 +5,7 @@ import { DefaultChatTransport } from "ai";
import { useEffect, useRef, useState, useCallback, useMemo } from "react";
import { createPortal } from "react-dom";
import useSWR, { useSWRConfig } from "swr";
-import { Send, Loader2, ImagePlus, Paperclip, X, Plus, History, LayoutGrid, Maximize2, RefreshCw, Globe, Box, ArrowUp, Video, Sparkles, Check, ChevronDown, ChevronUp, AlertCircle, CheckCircle2, Brain, ThumbsUp, ThumbsDown } from "lucide-react";
+import { Send, Loader2, ImagePlus, Paperclip, X, Plus, History, LayoutGrid, Maximize2, RefreshCw, Globe, Box, ArrowUp, Video, Sparkles, Check, ChevronDown, ChevronUp, AlertCircle, CheckCircle2, Brain, ThumbsUp, ThumbsDown, Eye } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import {
@@ -5492,8 +5492,9 @@ export function CanvasChatPanel({ chatId, initialMessages = [], onClose, onOpenF
{showModelMeta ? (
-
- ◈ {assistantModelName}
+
+
+ {assistantModelName}
) : null}
{showVoteActions ? (
diff --git a/components/message.tsx b/components/message.tsx
index a346590d5..77a96e231 100644
--- a/components/message.tsx
+++ b/components/message.tsx
@@ -1,6 +1,7 @@
"use client";
import type { UseChatHelpers } from "@ai-sdk/react";
import equal from "fast-deep-equal";
+import { Eye } from "lucide-react";
import { memo, useState } from "react";
import type { Vote } from "@/lib/db/schema";
import type { ChatMessage } from "@/lib/types";
@@ -174,18 +175,22 @@ function filterAgentRoutingNoise(text: string): string {
}
const IMAGE_DONE_SUMMARY = "已完成本次生成,如需微调可继续告诉我。";
-const MODEL_BADGE_REGEX =
- /^\s*[◈◇◆🔹⬡✦•·]\s*[A-Za-z][A-Za-z0-9 .:+\-_/()]{2,}\s*$/im;
+const MODEL_BADGE_LINE_REGEX =
+ /^\s*[◈◇◆🔹⬡✦•·]\s*([A-Za-z][A-Za-z0-9 .:+\-_/()]{2,})\s*$/im;
+const MODEL_BADGE_LINE_GLOBAL_REGEX =
+ /^\s*[◈◇◆🔹⬡✦•·]\s*[A-Za-z][A-Za-z0-9 .:+\-_/()]{2,}\s*$/gim;
-function ensureImageModelBadge(text: string, fallbackModelName?: string): string {
- if (!text) return text;
- const normalized = String(text || "").trim();
- if (!normalized) return normalized;
- const modelName = String(fallbackModelName || "").trim();
- if (!modelName) return normalized;
- if (!/!\[[^\]]*\]\((https?:\/\/[^\s)]+)\)/i.test(normalized)) return normalized;
- if (MODEL_BADGE_REGEX.test(normalized)) return normalized;
- return `◈ ${modelName}\n\n${normalized}`;
+function extractModelBadgeName(text: string): string {
+ if (!text) return "";
+ const match = String(text || "").match(MODEL_BADGE_LINE_REGEX);
+ return match?.[1]?.trim() || "";
+}
+
+function stripModelBadgeLines(text: string): string {
+ return String(text || "")
+ .replace(MODEL_BADGE_LINE_GLOBAL_REGEX, "")
+ .replace(/\n{3,}/g, "\n\n")
+ .trim();
}
function appendImageDoneSummary(text: string): string {
@@ -342,19 +347,39 @@ const PurePreviewMessage = ({
}
// 应用视频内容过滤
+ const routedFilteredText =
+ message.role === "assistant"
+ ? filterAgentRoutingNoise(filterVideoContent(part.text))
+ : part.text;
+ const extractedModelName =
+ message.role === "assistant"
+ ? extractModelBadgeName(routedFilteredText)
+ : "";
+ const contentWithoutBadge =
+ message.role === "assistant"
+ ? stripModelBadgeLines(routedFilteredText)
+ : routedFilteredText;
+ const inferredFallbackModelName =
+ message.role === "assistant" &&
+ !extractedModelName &&
+ extractImageUrlsFromText(contentWithoutBadge).length > 0
+ ? String(fallbackImageModelName || "").trim()
+ : "";
+ const displayModelName = extractedModelName || inferredFallbackModelName;
const filteredText =
message.role === "assistant"
- ? appendImageDoneSummary(
- ensureImageModelBadge(
- filterAgentRoutingNoise(filterVideoContent(part.text)),
- fallbackImageModelName
- )
- )
- : part.text;
+ ? appendImageDoneSummary(contentWithoutBadge)
+ : contentWithoutBadge;
const textParts = parseAnnotations(filteredText);
return (
+ {message.role === "assistant" && displayModelName ? (
+
+
+ {displayModelName}
+
+ ) : null}