diff --git a/web/src/components/deer-flow/markdown.tsx b/web/src/components/deer-flow/markdown.tsx
index e36319b..1e70474 100644
--- a/web/src/components/deer-flow/markdown.tsx
+++ b/web/src/components/deer-flow/markdown.tsx
@@ -13,6 +13,7 @@ import "katex/dist/katex.min.css";
import { Button } from "~/components/ui/button";
import { rehypeSplitWordsIntoSpans } from "~/core/rehype";
+import { autoFixMarkdown } from "~/core/utils/markdown";
import { cn } from "~/lib/utils";
import Image from "./image";
@@ -62,7 +63,9 @@ export function Markdown({
}}
{...props}
>
- {dropMarkdownQuote(processKatexInMarkdown(children))}
+ {autoFixMarkdown(
+ dropMarkdownQuote(processKatexInMarkdown(children ?? "")) ?? "",
+ )}
{enableCopy && typeof children === "string" && (
diff --git a/web/src/core/utils/markdown.ts b/web/src/core/utils/markdown.ts
new file mode 100644
index 0000000..8b4a70f
--- /dev/null
+++ b/web/src/core/utils/markdown.ts
@@ -0,0 +1,57 @@
+export function autoFixMarkdown(markdown: string): string {
+ return autoCloseTrailingLink(markdown);
+}
+
+function autoCloseTrailingLink(markdown: string): string {
+ // Fix unclosed Markdown links or images
+ let fixedMarkdown: string = markdown;
+
+ // Fix unclosed image syntax 
+ fixedMarkdown = fixedMarkdown.replace(
+ /!\[([^\]]*)\]\(([^)]*)$/g,
+ (match: string, altText: string, url: string): string => {
+ return ``;
+ },
+ );
+
+ // Fix unclosed link syntax [...](...)
+ fixedMarkdown = fixedMarkdown.replace(
+ /\[([^\]]*)\]\(([^)]*)$/g,
+ (match: string, linkText: string, url: string): string => {
+ return `[${linkText}](${url})`;
+ },
+ );
+
+ // Fix unclosed image syntax ![...]
+ fixedMarkdown = fixedMarkdown.replace(
+ /!\[([^\]]*)$/g,
+ (match: string, altText: string): string => {
+ return `![${altText}]`;
+ },
+ );
+
+ // Fix unclosed link syntax [...]
+ fixedMarkdown = fixedMarkdown.replace(
+ /\[([^\]]*)$/g,
+ (match: string, linkText: string): string => {
+ return `[${linkText}]`;
+ },
+ );
+
+ // Fix unclosed images or links missing ")"
+ fixedMarkdown = fixedMarkdown.replace(
+ /!\[([^\]]*)\]\(([^)]*)$/g,
+ (match: string, altText: string, url: string): string => {
+ return ``;
+ },
+ );
+
+ fixedMarkdown = fixedMarkdown.replace(
+ /\[([^\]]*)\]\(([^)]*)$/g,
+ (match: string, linkText: string, url: string): string => {
+ return `[${linkText}](${url})`;
+ },
+ );
+
+ return fixedMarkdown;
+}