@hkyhy/marsun-components-core 0.1.11 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -6
- package/dist/components/AgentHub/Chat/Action/CreateButton.js +8 -0
- package/dist/components/AgentHub/Chat/Action/CreateButton.js.map +1 -0
- package/dist/components/AgentHub/Chat/Action/ManageActionButtons.js +20 -0
- package/dist/components/AgentHub/Chat/Action/ManageActionButtons.js.map +1 -0
- package/dist/components/AgentHub/Chat/Action/SessionActionButtons.js +24 -0
- package/dist/components/AgentHub/Chat/Action/SessionActionButtons.js.map +1 -0
- package/dist/components/AgentHub/Chat/Action/handlers.d.ts +0 -5
- package/dist/components/AgentHub/Chat/Detail/ChatInput/index.js +65 -0
- package/dist/components/AgentHub/Chat/Detail/ChatInput/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/ChatInput/style.module.scss.js +12 -0
- package/dist/components/AgentHub/Chat/Detail/ChatInput/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/ChatPanel/index.d.ts +31 -0
- package/dist/components/AgentHub/Chat/Detail/ChatPanel/index.js +85 -0
- package/dist/components/AgentHub/Chat/Detail/ChatPanel/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/ChatPanel/style.module.scss.js +14 -0
- package/dist/components/AgentHub/Chat/Detail/ChatPanel/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/ChatSuggestionRow/index.d.ts +9 -0
- package/dist/components/AgentHub/Chat/Detail/ChatSuggestionRow/index.js +22 -0
- package/dist/components/AgentHub/Chat/Detail/ChatSuggestionRow/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/ChatSuggestionRow/style.module.scss.js +8 -0
- package/dist/components/AgentHub/Chat/Detail/ChatSuggestionRow/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationContent/index.js +21 -0
- package/dist/components/AgentHub/Chat/Detail/CitationContent/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationContent/style.module.scss.js +8 -0
- package/dist/components/AgentHub/Chat/Detail/CitationContent/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationInlineBadge/index.js +17 -0
- package/dist/components/AgentHub/Chat/Detail/CitationInlineBadge/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationInlineBadge/style.module.scss.js +7 -0
- package/dist/components/AgentHub/Chat/Detail/CitationInlineBadge/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationMarkdownContent/index.js +68 -0
- package/dist/components/AgentHub/Chat/Detail/CitationMarkdownContent/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationMarkdownContent/style.module.scss.js +7 -0
- package/dist/components/AgentHub/Chat/Detail/CitationMarkdownContent/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationPanel/index.js +247 -0
- package/dist/components/AgentHub/Chat/Detail/CitationPanel/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/CitationPanel/style.module.scss.js +31 -0
- package/dist/components/AgentHub/Chat/Detail/CitationPanel/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MermaidBlock/index.js +43 -0
- package/dist/components/AgentHub/Chat/Detail/MermaidBlock/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MermaidBlock/style.module.scss.js +8 -0
- package/dist/components/AgentHub/Chat/Detail/MermaidBlock/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MessageActions/index.js +103 -0
- package/dist/components/AgentHub/Chat/Detail/MessageActions/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MessageActions/style.module.scss.js +14 -0
- package/dist/components/AgentHub/Chat/Detail/MessageActions/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MessageEditPopover/index.js +58 -0
- package/dist/components/AgentHub/Chat/Detail/MessageEditPopover/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MessageEditPopover/style.module.scss.js +9 -0
- package/dist/components/AgentHub/Chat/Detail/MessageEditPopover/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MessageItem/index.js +309 -0
- package/dist/components/AgentHub/Chat/Detail/MessageItem/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/MessageItem/style.module.scss.js +24 -0
- package/dist/components/AgentHub/Chat/Detail/MessageItem/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/ThinkingSection/index.js +122 -0
- package/dist/components/AgentHub/Chat/Detail/ThinkingSection/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/ThinkingSection/style.module.scss.js +25 -0
- package/dist/components/AgentHub/Chat/Detail/ThinkingSection/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Detail/index.d.ts +12 -0
- package/dist/components/AgentHub/Chat/Form/Form.js +37 -0
- package/dist/components/AgentHub/Chat/Form/Form.js.map +1 -0
- package/dist/components/AgentHub/Chat/List/ChatCard/index.js +86 -0
- package/dist/components/AgentHub/Chat/List/ChatCard/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/List/ChatCard/style.module.scss.js +25 -0
- package/dist/components/AgentHub/Chat/List/ChatCard/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/List/FilterBar.js +17 -0
- package/dist/components/AgentHub/Chat/List/FilterBar.js.map +1 -0
- package/dist/components/AgentHub/Chat/List/SessionSidebar/index.js +156 -0
- package/dist/components/AgentHub/Chat/List/SessionSidebar/index.js.map +1 -0
- package/dist/components/AgentHub/Chat/List/SessionSidebar/style.module.scss.js +28 -0
- package/dist/components/AgentHub/Chat/List/SessionSidebar/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/Chat/Modal/FormModal.js +58 -0
- package/dist/components/AgentHub/Chat/Modal/FormModal.js.map +1 -0
- package/dist/components/AgentHub/Chat/hooks/useAutoScrollToBottom.js +35 -0
- package/dist/components/AgentHub/Chat/hooks/useAutoScrollToBottom.js.map +1 -0
- package/dist/components/AgentHub/Chat/hooks/useChat.js +51 -0
- package/dist/components/AgentHub/Chat/hooks/useChat.js.map +1 -0
- package/dist/components/AgentHub/Chat/hooks/useChatSessions.js +60 -0
- package/dist/components/AgentHub/Chat/hooks/useChatSessions.js.map +1 -0
- package/dist/components/AgentHub/Chat/hooks/useSSECompletion.js +69 -0
- package/dist/components/AgentHub/Chat/hooks/useSSECompletion.js.map +1 -0
- package/dist/components/AgentHub/Chat/hooks/useTypewriter.js +39 -0
- package/dist/components/AgentHub/Chat/hooks/useTypewriter.js.map +1 -0
- package/dist/components/AgentHub/Chat/index.d.ts +1 -0
- package/dist/components/AgentHub/Chat/utils/citationContent.js +169 -0
- package/dist/components/AgentHub/Chat/utils/citationContent.js.map +1 -0
- package/dist/components/AgentHub/Chat/utils/messageContent.js +85 -0
- package/dist/components/AgentHub/Chat/utils/messageContent.js.map +1 -0
- package/dist/components/AgentHub/Chat/utils/sanitizeMermaidChart.js +22 -0
- package/dist/components/AgentHub/Chat/utils/sanitizeMermaidChart.js.map +1 -0
- package/dist/components/AgentHub/Chat/utils/sessionMessages.js +151 -0
- package/dist/components/AgentHub/Chat/utils/sessionMessages.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Action/CreateButton.js +8 -0
- package/dist/components/AgentHub/KnowledgeBase/Action/CreateButton.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Action/ManageActionButtons.js +20 -0
- package/dist/components/AgentHub/KnowledgeBase/Action/ManageActionButtons.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/DocumentTable/index.js +110 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/DocumentTable/index.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/DocumentTable/style.module.scss.js +7 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/DocumentTable/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/ParseStatusTag/index.js +18 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/ParseStatusTag/index.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/ParseStatusTag/style.module.scss.js +7 -0
- package/dist/components/AgentHub/KnowledgeBase/Detail/ParseStatusTag/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Form/Form.js +31 -0
- package/dist/components/AgentHub/KnowledgeBase/Form/Form.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/List/FilterBar.js +17 -0
- package/dist/components/AgentHub/KnowledgeBase/List/FilterBar.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/List/KnowledgeCard/index.js +118 -0
- package/dist/components/AgentHub/KnowledgeBase/List/KnowledgeCard/index.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/List/KnowledgeCard/style.module.scss.js +23 -0
- package/dist/components/AgentHub/KnowledgeBase/List/KnowledgeCard/style.module.scss.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/Modal/FormModal.js +47 -0
- package/dist/components/AgentHub/KnowledgeBase/Modal/FormModal.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/constants/types.js +28 -0
- package/dist/components/AgentHub/KnowledgeBase/constants/types.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/hooks/useKBDocuments.js +21 -0
- package/dist/components/AgentHub/KnowledgeBase/hooks/useKBDocuments.js.map +1 -0
- package/dist/components/AgentHub/KnowledgeBase/hooks/useKnowledgeBase.js +32 -0
- package/dist/components/AgentHub/KnowledgeBase/hooks/useKnowledgeBase.js.map +1 -0
- package/dist/components/Filter/FilterDateRange/index.d.ts +2 -0
- package/dist/components/Filter/FilterDateRange/index.js +62 -51
- package/dist/components/Filter/FilterDateRange/index.js.map +1 -1
- package/dist/components/Filter/FilterSelect/index.d.ts +6 -2
- package/dist/components/Filter/FilterSelect/index.js +132 -107
- package/dist/components/Filter/FilterSelect/index.js.map +1 -1
- package/dist/components/Filter/FilterTrigger/index.d.ts +2 -2
- package/dist/components/Filter/FilterTrigger/index.js.map +1 -1
- package/dist/components/Filter/FilterTrigger/style.module.scss.js +4 -4
- package/dist/components/Filter/index.d.ts +1 -1
- package/dist/components/Icons/index.js +153 -145
- package/dist/components/Icons/index.js.map +1 -1
- package/dist/components/LlmFormattedText/LlmFormattedText/index.d.ts +8 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/index.js +42 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/index.js.map +1 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/style.module.scss.js +17 -0
- package/dist/components/LlmFormattedText/LlmFormattedText/style.module.scss.js.map +1 -0
- package/dist/components/LlmFormattedText/index.d.ts +4 -0
- package/dist/components/LlmFormattedText/parseLlmText.d.ts +14 -0
- package/dist/components/LlmFormattedText/parseLlmText.js +77 -0
- package/dist/components/LlmFormattedText/parseLlmText.js.map +1 -0
- package/dist/components/Sparkline/Sparkline/index.d.ts +11 -0
- package/dist/components/Sparkline/Sparkline/index.js +46 -0
- package/dist/components/Sparkline/Sparkline/index.js.map +1 -0
- package/dist/components/Sparkline/Sparkline/style.module.scss.js +8 -0
- package/dist/components/Sparkline/Sparkline/style.module.scss.js.map +1 -0
- package/dist/components/Sparkline/index.d.ts +2 -0
- package/dist/components/TooltipInfo/TooltipInfo.js +29 -20
- package/dist/components/TooltipInfo/TooltipInfo.js.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +291 -175
- package/dist/index.js.map +1 -1
- package/dist/marsun-components-core.css +1 -1
- package/dist/styles/global.css +1 -1
- package/dist/theme/constants.d.ts +47 -1
- package/dist/theme/constants.js +50 -5
- package/dist/theme/constants.js.map +1 -1
- package/dist/theme/index.d.ts +2 -2
- package/dist/theme/index.js +8 -6
- package/dist/theme/theme.d.ts +10 -0
- package/dist/theme/theme.js +24 -34
- package/dist/theme/theme.js.map +1 -1
- package/dist/theme/tokens.css +139 -0
- package/package.json +6 -3
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { normalizeCitation as J } from "../utils/citationContent.js";
|
|
2
|
+
import { useState as P, useRef as W, useCallback as S } from "react";
|
|
3
|
+
import { useMarsunFetch as q } from "../../../../provider/context.js";
|
|
4
|
+
const _ = ({ completionUrl: e, getAuthHeaders: n }) => {
|
|
5
|
+
const [C, o] = P(!1), a = W(null), i = q(), T = S(
|
|
6
|
+
async (r, x, N, O, c, k) => {
|
|
7
|
+
var u, d, m, b;
|
|
8
|
+
(u = a.current) == null || u.abort();
|
|
9
|
+
const l = new AbortController();
|
|
10
|
+
a.current = l, o(!0);
|
|
11
|
+
const R = ((d = [...r].reverse().find((t) => t.role === "user")) == null ? void 0 : d.content) ?? "", $ = e.startsWith("http") ? e : `${i.baseUrl ?? ""}${e}`;
|
|
12
|
+
try {
|
|
13
|
+
const t = await fetch($, {
|
|
14
|
+
method: "POST",
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/json",
|
|
17
|
+
...i.headers,
|
|
18
|
+
...n == null ? void 0 : n()
|
|
19
|
+
},
|
|
20
|
+
body: JSON.stringify({ question: R, stream: !0, session_id: k }),
|
|
21
|
+
signal: l.signal
|
|
22
|
+
});
|
|
23
|
+
if (!t.ok) {
|
|
24
|
+
c(await t.text() || `HTTP ${t.status}`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const p = (m = t.body) == null ? void 0 : m.getReader();
|
|
28
|
+
if (!p) {
|
|
29
|
+
c("No response body");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const j = new TextDecoder();
|
|
33
|
+
let f = "";
|
|
34
|
+
for (; ; ) {
|
|
35
|
+
const { done: v, value: D } = await p.read();
|
|
36
|
+
if (v) break;
|
|
37
|
+
f += j.decode(D, { stream: !0 });
|
|
38
|
+
const y = f.split(`
|
|
39
|
+
`);
|
|
40
|
+
f = y.pop() ?? "";
|
|
41
|
+
for (const h of y) {
|
|
42
|
+
if (!h.startsWith("data:")) continue;
|
|
43
|
+
const w = h.slice(5).trim();
|
|
44
|
+
if (w !== "[DONE]")
|
|
45
|
+
try {
|
|
46
|
+
const s = JSON.parse(w);
|
|
47
|
+
s.answer && x(s.answer), (b = s.citations) != null && b.length && N(s.citations.map((E) => J(E)));
|
|
48
|
+
} catch {
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
O();
|
|
53
|
+
} catch (t) {
|
|
54
|
+
t.name !== "AbortError" && c(t instanceof Error ? t.message : String(t));
|
|
55
|
+
} finally {
|
|
56
|
+
o(!1);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
[e, i, n]
|
|
60
|
+
), g = S(() => {
|
|
61
|
+
var r;
|
|
62
|
+
(r = a.current) == null || r.abort(), o(!1);
|
|
63
|
+
}, []);
|
|
64
|
+
return { send: T, streaming: C, abort: g };
|
|
65
|
+
};
|
|
66
|
+
export {
|
|
67
|
+
_ as useSSECompletion
|
|
68
|
+
};
|
|
69
|
+
//# sourceMappingURL=useSSECompletion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSSECompletion.js","sources":["../../../../../src/components/AgentHub/Chat/hooks/useSSECompletion.ts"],"sourcesContent":["import { normalizeCitation } from '@/components/AgentHub/Chat/utils/citationContent';\nimport { useMarsunFetch } from '@/provider';\nimport type { Citation } from '@/components/AgentHub/types';\nimport { useCallback, useRef, useState } from 'react';\n\nexport type SSECompletionOptions = {\n completionUrl: string;\n getAuthHeaders?: () => Record<string, string>;\n};\n\nexport const useSSECompletion = ({ completionUrl, getAuthHeaders }: SSECompletionOptions) => {\n const [streaming, setStreaming] = useState(false);\n const abortRef = useRef<AbortController | null>(null);\n const fetchCtx = useMarsunFetch();\n\n const send = useCallback(\n async (\n messages: { role: 'user' | 'assistant'; content: string }[],\n onChunk: (text: string) => void,\n onCitations: (citations: Citation[]) => void,\n onDone: () => void,\n onError: (err: string) => void,\n sessionId?: string,\n ) => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n setStreaming(true);\n\n const question = [...messages].reverse().find((m) => m.role === 'user')?.content ?? '';\n const url = completionUrl.startsWith('http')\n ? completionUrl\n : `${fetchCtx.baseUrl ?? ''}${completionUrl}`;\n\n try {\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...fetchCtx.headers,\n ...getAuthHeaders?.(),\n },\n body: JSON.stringify({ question, stream: true, session_id: sessionId }),\n signal: controller.signal,\n });\n\n if (!res.ok) {\n onError(await res.text() || `HTTP ${res.status}`);\n return;\n }\n\n const reader = res.body?.getReader();\n if (!reader) {\n onError('No response body');\n return;\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (payload === '[DONE]') continue;\n try {\n const json = JSON.parse(payload) as {\n answer?: string;\n citations?: Citation[];\n };\n if (json.answer) onChunk(json.answer);\n if (json.citations?.length) {\n onCitations(json.citations.map((c) => normalizeCitation(c as Record<string, unknown>)));\n }\n } catch {\n // skip malformed chunk\n }\n }\n }\n onDone();\n } catch (err) {\n if ((err as Error).name !== 'AbortError') {\n onError(err instanceof Error ? err.message : String(err));\n }\n } finally {\n setStreaming(false);\n }\n },\n [completionUrl, fetchCtx, getAuthHeaders],\n );\n\n const abort = useCallback(() => {\n abortRef.current?.abort();\n setStreaming(false);\n }, []);\n\n return { send, streaming, abort };\n};\n"],"names":["useSSECompletion","completionUrl","getAuthHeaders","streaming","setStreaming","useState","abortRef","useRef","fetchCtx","useMarsunFetch","send","useCallback","messages","onChunk","onCitations","onDone","onError","sessionId","_a","controller","question","_b","m","url","res","reader","_c","decoder","buffer","done","value","lines","line","payload","json","_d","c","normalizeCitation","err","abort"],"mappings":";;;AAUO,MAAMA,IAAmB,CAAC,EAAE,eAAAC,GAAe,gBAAAC,QAA2C;AAC3F,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAAS,EAAK,GAC1CC,IAAWC,EAA+B,IAAI,GAC9CC,IAAWC,EAAA,GAEXC,IAAOC;AAAA,IACX,OACEC,GACAC,GACAC,GACAC,GACAC,GACAC,MACG;;AACH,OAAAC,IAAAZ,EAAS,YAAT,QAAAY,EAAkB;AAClB,YAAMC,IAAa,IAAI,gBAAA;AACvB,MAAAb,EAAS,UAAUa,GACnBf,EAAa,EAAI;AAEjB,YAAMgB,MAAWC,IAAA,CAAC,GAAGT,CAAQ,EAAE,QAAA,EAAU,KAAK,CAACU,MAAMA,EAAE,SAAS,MAAM,MAArD,gBAAAD,EAAwD,YAAW,IAC9EE,IAAMtB,EAAc,WAAW,MAAM,IACvCA,IACA,GAAGO,EAAS,WAAW,EAAE,GAAGP,CAAa;AAE7C,UAAI;AACF,cAAMuB,IAAM,MAAM,MAAMD,GAAK;AAAA,UAC3B,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,GAAGf,EAAS;AAAA,YACZ,GAAGN,KAAA,gBAAAA;AAAA,UAAiB;AAAA,UAEtB,MAAM,KAAK,UAAU,EAAE,UAAAkB,GAAU,QAAQ,IAAM,YAAYH,GAAW;AAAA,UACtE,QAAQE,EAAW;AAAA,QAAA,CACpB;AAED,YAAI,CAACK,EAAI,IAAI;AACX,UAAAR,EAAQ,MAAMQ,EAAI,KAAA,KAAU,QAAQA,EAAI,MAAM,EAAE;AAChD;AAAA,QACF;AAEA,cAAMC,KAASC,IAAAF,EAAI,SAAJ,gBAAAE,EAAU;AACzB,YAAI,CAACD,GAAQ;AACX,UAAAT,EAAQ,kBAAkB;AAC1B;AAAA,QACF;AAEA,cAAMW,IAAU,IAAI,YAAA;AACpB,YAAIC,IAAS;AAEb,mBAAa;AACX,gBAAM,EAAE,MAAAC,GAAM,OAAAC,EAAA,IAAU,MAAML,EAAO,KAAA;AACrC,cAAII,EAAM;AACV,UAAAD,KAAUD,EAAQ,OAAOG,GAAO,EAAE,QAAQ,IAAM;AAChD,gBAAMC,IAAQH,EAAO,MAAM;AAAA,CAAI;AAC/B,UAAAA,IAASG,EAAM,SAAS;AACxB,qBAAWC,KAAQD,GAAO;AACxB,gBAAI,CAACC,EAAK,WAAW,OAAO,EAAG;AAC/B,kBAAMC,IAAUD,EAAK,MAAM,CAAC,EAAE,KAAA;AAC9B,gBAAIC,MAAY;AAChB,kBAAI;AACF,sBAAMC,IAAO,KAAK,MAAMD,CAAO;AAI/B,gBAAIC,EAAK,UAAQrB,EAAQqB,EAAK,MAAM,IAChCC,IAAAD,EAAK,cAAL,QAAAC,EAAgB,UAClBrB,EAAYoB,EAAK,UAAU,IAAI,CAACE,MAAMC,EAAkBD,CAA4B,CAAC,CAAC;AAAA,cAE1F,QAAQ;AAAA,cAER;AAAA,UACF;AAAA,QACF;AACA,QAAArB,EAAA;AAAA,MACF,SAASuB,GAAK;AACZ,QAAKA,EAAc,SAAS,gBAC1BtB,EAAQsB,aAAe,QAAQA,EAAI,UAAU,OAAOA,CAAG,CAAC;AAAA,MAE5D,UAAA;AACE,QAAAlC,EAAa,EAAK;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAACH,GAAeO,GAAUN,CAAc;AAAA,EAAA,GAGpCqC,IAAQ5B,EAAY,MAAM;;AAC9B,KAAAO,IAAAZ,EAAS,YAAT,QAAAY,EAAkB,SAClBd,EAAa,EAAK;AAAA,EACpB,GAAG,CAAA,CAAE;AAEL,SAAO,EAAE,MAAAM,GAAM,WAAAP,GAAW,OAAAoC,EAAA;AAC5B;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useRef as t, useState as M, useEffect as s } from "react";
|
|
2
|
+
function q(e, u, w = {}) {
|
|
3
|
+
const { charsPerSecond: h = 60 } = w, n = t(u), [r, g] = M(() => u ? 0 : e.length), f = t(0), p = t(0), i = t(0), l = t(performance.now()), a = t(e.length), c = t(r);
|
|
4
|
+
a.current = e.length, c.current = r, s(() => {
|
|
5
|
+
u && (n.current = !0);
|
|
6
|
+
}, [u]);
|
|
7
|
+
const d = n.current && r < e.length;
|
|
8
|
+
return s(() => {
|
|
9
|
+
if (!d) return;
|
|
10
|
+
let m = !0;
|
|
11
|
+
const R = (y) => {
|
|
12
|
+
if (!m) return;
|
|
13
|
+
const L = a.current, A = c.current;
|
|
14
|
+
if (A >= L) return;
|
|
15
|
+
const F = y - l.current;
|
|
16
|
+
l.current = y;
|
|
17
|
+
const T = h * F / 1e3 + i.current, o = Math.floor(T);
|
|
18
|
+
if (i.current = T - o, o > 0) {
|
|
19
|
+
const v = Math.min(A + o, L);
|
|
20
|
+
c.current = v, g(v);
|
|
21
|
+
}
|
|
22
|
+
c.current < a.current && (f.current = requestAnimationFrame(R));
|
|
23
|
+
};
|
|
24
|
+
return l.current = performance.now(), f.current = requestAnimationFrame(R), () => {
|
|
25
|
+
m = !1, cancelAnimationFrame(f.current);
|
|
26
|
+
};
|
|
27
|
+
}, [e.length, h, d]), s(() => {
|
|
28
|
+
r >= e.length && e.length > 0 && (n.current = !1);
|
|
29
|
+
}, [r, e.length]), s(() => {
|
|
30
|
+
e.length === 0 && p.current > 0 && (n.current = !1, c.current = 0, g(0), i.current = 0), p.current = e.length;
|
|
31
|
+
}, [e.length]), {
|
|
32
|
+
displayed: e.slice(0, r),
|
|
33
|
+
isTyping: n.current && r < e.length
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
q as useTypewriter
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=useTypewriter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTypewriter.js","sources":["../../../../../src/components/AgentHub/Chat/hooks/useTypewriter.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\n\ninterface UseTypewriterOptions {\n /** Fixed reveal rate in characters per second. Default: 60 */\n charsPerSecond?: number;\n}\n\n/**\n * Smoothly reveals streaming text character-by-character using requestAnimationFrame.\n *\n * Live streaming messages animate from empty; once the stream ends, any remaining\n * characters continue at the same rate until fully revealed. Historical messages\n * with `streaming: false` that were never streamed show in full immediately.\n */\nexport function useTypewriter(\n content: string,\n streaming: boolean,\n options: UseTypewriterOptions = {},\n) {\n const { charsPerSecond = 60 } = options;\n\n const wasStreamingRef = useRef(streaming);\n const [displayedLength, setDisplayedLength] = useState(() => (streaming ? 0 : content.length));\n const rafRef = useRef<number>(0);\n const prevContentLenRef = useRef(0);\n const carryRef = useRef(0);\n const lastTimeRef = useRef(performance.now());\n const contentLengthRef = useRef(content.length);\n const displayedLengthRef = useRef(displayedLength);\n\n contentLengthRef.current = content.length;\n displayedLengthRef.current = displayedLength;\n\n useEffect(() => {\n if (streaming) {\n wasStreamingRef.current = true;\n }\n }, [streaming]);\n\n const isPendingReveal =\n wasStreamingRef.current && displayedLength < content.length;\n\n useEffect(() => {\n if (!isPendingReveal) return;\n\n let running = true;\n\n const loop = (now: number) => {\n if (!running) return;\n\n const target = contentLengthRef.current;\n const prev = displayedLengthRef.current;\n if (prev >= target) return;\n\n const deltaMs = now - lastTimeRef.current;\n lastTimeRef.current = now;\n\n const charsToAdd = (charsPerSecond * deltaMs) / 1000 + carryRef.current;\n const step = Math.floor(charsToAdd);\n carryRef.current = charsToAdd - step;\n\n if (step > 0) {\n const next = Math.min(prev + step, target);\n displayedLengthRef.current = next;\n setDisplayedLength(next);\n }\n\n if (displayedLengthRef.current < contentLengthRef.current) {\n rafRef.current = requestAnimationFrame(loop);\n }\n };\n\n lastTimeRef.current = performance.now();\n rafRef.current = requestAnimationFrame(loop);\n\n return () => {\n running = false;\n cancelAnimationFrame(rafRef.current);\n };\n }, [content.length, charsPerSecond, isPendingReveal]);\n\n useEffect(() => {\n if (displayedLength >= content.length && content.length > 0) {\n wasStreamingRef.current = false;\n }\n }, [displayedLength, content.length]);\n\n useEffect(() => {\n if (content.length === 0 && prevContentLenRef.current > 0) {\n wasStreamingRef.current = false;\n displayedLengthRef.current = 0;\n setDisplayedLength(0);\n carryRef.current = 0;\n }\n prevContentLenRef.current = content.length;\n }, [content.length]);\n\n return {\n displayed: content.slice(0, displayedLength),\n isTyping: wasStreamingRef.current && displayedLength < content.length,\n };\n}\n"],"names":["useTypewriter","content","streaming","options","charsPerSecond","wasStreamingRef","useRef","displayedLength","setDisplayedLength","useState","rafRef","prevContentLenRef","carryRef","lastTimeRef","contentLengthRef","displayedLengthRef","useEffect","isPendingReveal","running","loop","now","target","prev","deltaMs","charsToAdd","step","next"],"mappings":";AAcO,SAASA,EACdC,GACAC,GACAC,IAAgC,CAAA,GAChC;AACA,QAAM,EAAE,gBAAAC,IAAiB,GAAA,IAAOD,GAE1BE,IAAkBC,EAAOJ,CAAS,GAClC,CAACK,GAAiBC,CAAkB,IAAIC,EAAS,MAAOP,IAAY,IAAID,EAAQ,MAAO,GACvFS,IAASJ,EAAe,CAAC,GACzBK,IAAoBL,EAAO,CAAC,GAC5BM,IAAWN,EAAO,CAAC,GACnBO,IAAcP,EAAO,YAAY,IAAA,CAAK,GACtCQ,IAAmBR,EAAOL,EAAQ,MAAM,GACxCc,IAAqBT,EAAOC,CAAe;AAEjD,EAAAO,EAAiB,UAAUb,EAAQ,QACnCc,EAAmB,UAAUR,GAE7BS,EAAU,MAAM;AACd,IAAId,MACFG,EAAgB,UAAU;AAAA,EAE9B,GAAG,CAACH,CAAS,CAAC;AAEd,QAAMe,IACJZ,EAAgB,WAAWE,IAAkBN,EAAQ;AAEvD,SAAAe,EAAU,MAAM;AACd,QAAI,CAACC,EAAiB;AAEtB,QAAIC,IAAU;AAEd,UAAMC,IAAO,CAACC,MAAgB;AAC5B,UAAI,CAACF,EAAS;AAEd,YAAMG,IAASP,EAAiB,SAC1BQ,IAAOP,EAAmB;AAChC,UAAIO,KAAQD,EAAQ;AAEpB,YAAME,IAAUH,IAAMP,EAAY;AAClC,MAAAA,EAAY,UAAUO;AAEtB,YAAMI,IAAcpB,IAAiBmB,IAAW,MAAOX,EAAS,SAC1Da,IAAO,KAAK,MAAMD,CAAU;AAGlC,UAFAZ,EAAS,UAAUY,IAAaC,GAE5BA,IAAO,GAAG;AACZ,cAAMC,IAAO,KAAK,IAAIJ,IAAOG,GAAMJ,CAAM;AACzC,QAAAN,EAAmB,UAAUW,GAC7BlB,EAAmBkB,CAAI;AAAA,MACzB;AAEA,MAAIX,EAAmB,UAAUD,EAAiB,YAChDJ,EAAO,UAAU,sBAAsBS,CAAI;AAAA,IAE/C;AAEA,WAAAN,EAAY,UAAU,YAAY,IAAA,GAClCH,EAAO,UAAU,sBAAsBS,CAAI,GAEpC,MAAM;AACX,MAAAD,IAAU,IACV,qBAAqBR,EAAO,OAAO;AAAA,IACrC;AAAA,EACF,GAAG,CAACT,EAAQ,QAAQG,GAAgBa,CAAe,CAAC,GAEpDD,EAAU,MAAM;AACd,IAAIT,KAAmBN,EAAQ,UAAUA,EAAQ,SAAS,MACxDI,EAAgB,UAAU;AAAA,EAE9B,GAAG,CAACE,GAAiBN,EAAQ,MAAM,CAAC,GAEpCe,EAAU,MAAM;AACd,IAAIf,EAAQ,WAAW,KAAKU,EAAkB,UAAU,MACtDN,EAAgB,UAAU,IAC1BU,EAAmB,UAAU,GAC7BP,EAAmB,CAAC,GACpBI,EAAS,UAAU,IAErBD,EAAkB,UAAUV,EAAQ;AAAA,EACtC,GAAG,CAACA,EAAQ,MAAM,CAAC,GAEZ;AAAA,IACL,WAAWA,EAAQ,MAAM,GAAGM,CAAe;AAAA,IAC3C,UAAUF,EAAgB,WAAWE,IAAkBN,EAAQ;AAAA,EAAA;AAEnE;"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const a = "#cite-", f = new RegExp("\\[ID[:-](\\d+)\\]|[((]ID[:-](\\d+)[))]|(?<![\\w\\[((])ID[:-](\\d+)(?![\\w])", "g");
|
|
2
|
+
function d(t) {
|
|
3
|
+
const n = [], e = new RegExp(f.source, f.flags);
|
|
4
|
+
let i = e.exec(t);
|
|
5
|
+
for (; i; ) {
|
|
6
|
+
const o = i[1] ?? i[2] ?? i[3];
|
|
7
|
+
n.push(parseInt(o, 10)), i = e.exec(t);
|
|
8
|
+
}
|
|
9
|
+
return n;
|
|
10
|
+
}
|
|
11
|
+
function _(t) {
|
|
12
|
+
return d(t);
|
|
13
|
+
}
|
|
14
|
+
function v(t, n) {
|
|
15
|
+
if (n <= 0) return 0;
|
|
16
|
+
const e = d(t).map(
|
|
17
|
+
(i) => p(i, n, t)
|
|
18
|
+
);
|
|
19
|
+
return new Set(e).size;
|
|
20
|
+
}
|
|
21
|
+
function g(t, n) {
|
|
22
|
+
const e = _(t);
|
|
23
|
+
if (e.length === 0 || n <= 0 || e.some((s) => s === 0)) return "zero";
|
|
24
|
+
if (e.some((s) => s === n)) return "one";
|
|
25
|
+
const i = e.every((s) => s >= 0 && s < n), o = e.every((s) => s >= 1 && s <= n);
|
|
26
|
+
if (o && !i) return "one";
|
|
27
|
+
if (i && !o) return "zero";
|
|
28
|
+
const c = [...new Set(e)].sort((s, r) => s - r);
|
|
29
|
+
return c[0] === 1 && c.length > 0 && c.every((s, r) => s === r + 1) ? "one" : "zero";
|
|
30
|
+
}
|
|
31
|
+
function A(t) {
|
|
32
|
+
return t.replace(f, (n, e, i, o) => {
|
|
33
|
+
const c = e ?? i ?? o;
|
|
34
|
+
return `[${c}](${a}${c})`;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function S(t) {
|
|
38
|
+
if (!(t != null && t.startsWith(a))) return null;
|
|
39
|
+
const n = parseInt(t.slice(a.length), 10);
|
|
40
|
+
return Number.isNaN(n) ? null : n;
|
|
41
|
+
}
|
|
42
|
+
function p(t, n, e) {
|
|
43
|
+
if (n <= 0) return 0;
|
|
44
|
+
const o = (e ? g(e, n) : "zero") === "one" ? t - 1 : t;
|
|
45
|
+
return o >= 0 && o < n ? o : Math.max(0, Math.min(o, n - 1));
|
|
46
|
+
}
|
|
47
|
+
function E(t, n, e) {
|
|
48
|
+
return p(t, n, e) + 1;
|
|
49
|
+
}
|
|
50
|
+
function m(t) {
|
|
51
|
+
return t.replace(/^\s*---[\s\S]*?---\s*/m, "").trim();
|
|
52
|
+
}
|
|
53
|
+
const y = /^<\/?[\w-]+(?:\s[^>]*)?>$/, T = /^\|?\s*:?-{3,}/, l = (t) => t.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim(), u = (t) => {
|
|
54
|
+
const n = t.trim();
|
|
55
|
+
return !(!n || n.length > 48 || y.test(n) || /^<\w/.test(n));
|
|
56
|
+
}, h = (t) => t.replace(/^<p[^>]*>/i, "").replace(/<\/p>$/i, "").trim(), b = (t) => {
|
|
57
|
+
const n = t.match(/<tbody[^>]*>[\s\S]*?<tr[^>]*>[\s\S]*?<td[^>]*>([\s\S]*?)<\/td>/i);
|
|
58
|
+
if (n != null && n[1]) {
|
|
59
|
+
const i = l(n[1]);
|
|
60
|
+
if (i) return i;
|
|
61
|
+
}
|
|
62
|
+
const e = t.match(/<th[^>]*>([\s\S]*?)<\/th>/i);
|
|
63
|
+
if (e != null && e[1]) {
|
|
64
|
+
const i = l(e[1]);
|
|
65
|
+
if (i) return i;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}, x = (t) => {
|
|
69
|
+
var e, i;
|
|
70
|
+
const n = [];
|
|
71
|
+
return t.split(`
|
|
72
|
+
`).forEach((o) => {
|
|
73
|
+
const c = o.trim();
|
|
74
|
+
if (!c.includes("|") || T.test(c.replace(/\|/g, ""))) return;
|
|
75
|
+
const s = c.split("|").map((r) => r.trim()).filter((r) => r.length > 0);
|
|
76
|
+
s.length >= 2 && n.push(s);
|
|
77
|
+
}), n.length >= 2 ? ((e = n[1]) == null ? void 0 : e[0]) ?? null : n.length === 1 ? ((i = n[0]) == null ? void 0 : i[0]) ?? null : null;
|
|
78
|
+
};
|
|
79
|
+
function M(t) {
|
|
80
|
+
if (!(t != null && t.trim())) return;
|
|
81
|
+
const n = t.trim().replace(/\\/g, "/"), e = n.split("/").pop() ?? n;
|
|
82
|
+
return e.replace(/\.(md|pdf|txt|docx?)$/i, "") || e;
|
|
83
|
+
}
|
|
84
|
+
function $(t) {
|
|
85
|
+
const n = t.doc_name ?? t.document_name, e = t.doc_id ?? t.document_id, i = typeof t.score == "number" ? t.score : typeof t.similarity == "number" ? t.similarity : void 0;
|
|
86
|
+
let o = t.page_no;
|
|
87
|
+
if (o == null && Array.isArray(t.positions) && t.positions.length > 0) {
|
|
88
|
+
const c = t.positions[0];
|
|
89
|
+
Array.isArray(c) && typeof c[0] == "number" && c[0] > 0 && (o = c[0]);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
id: typeof t.id == "string" ? t.id : String(t.doc_id ?? t.document_id ?? Math.random()),
|
|
93
|
+
doc_id: typeof e == "string" ? e : void 0,
|
|
94
|
+
doc_name: typeof n == "string" ? n : void 0,
|
|
95
|
+
dataset_id: typeof t.dataset_id == "string" ? t.dataset_id : void 0,
|
|
96
|
+
content: typeof t.content == "string" ? t.content : void 0,
|
|
97
|
+
score: i,
|
|
98
|
+
positions: Array.isArray(t.positions) ? t.positions : void 0,
|
|
99
|
+
page_no: o ?? null
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function R(t, n) {
|
|
103
|
+
const e = m(t), i = e.match(/^#{1,6}\s+(.+)$/m);
|
|
104
|
+
if (i != null && i[1] && u(i[1])) return i[1].trim();
|
|
105
|
+
const o = e.match(/<h[1-6][^>]*>([\s\S]*?)<\/h[1-6]>/i);
|
|
106
|
+
if (o != null && o[1]) {
|
|
107
|
+
const r = l(o[1]);
|
|
108
|
+
if (u(r)) return r;
|
|
109
|
+
}
|
|
110
|
+
if (/<table/i.test(e)) {
|
|
111
|
+
const r = b(e);
|
|
112
|
+
if (r && u(r)) return r;
|
|
113
|
+
}
|
|
114
|
+
const c = h(e);
|
|
115
|
+
if (c.includes("|")) {
|
|
116
|
+
const r = x(c);
|
|
117
|
+
if (r && u(r)) return r;
|
|
118
|
+
}
|
|
119
|
+
const s = e.split(`
|
|
120
|
+
`).map((r) => l(r.trim())).find((r) => r.length > 0 && !r.startsWith("|") && u(r));
|
|
121
|
+
return s || n;
|
|
122
|
+
}
|
|
123
|
+
function z(t, n) {
|
|
124
|
+
var e;
|
|
125
|
+
return ((e = t.doc_name) == null ? void 0 : e.trim()) || `来源 ${n + 1}`;
|
|
126
|
+
}
|
|
127
|
+
function C(t) {
|
|
128
|
+
const n = t;
|
|
129
|
+
if (!(n != null && n.length)) return;
|
|
130
|
+
const e = n[0];
|
|
131
|
+
if (!(e != null && e.length)) return;
|
|
132
|
+
const i = e[0];
|
|
133
|
+
return typeof i == "number" && i > 0 ? `第 ${i} 页` : `位置 ${e.join(", ")}`;
|
|
134
|
+
}
|
|
135
|
+
function N(t) {
|
|
136
|
+
const n = [], e = C(t.positions);
|
|
137
|
+
return e && n.push(e), t.score !== void 0 && n.push(`匹配 ${(t.score * 100).toFixed(0)}%`), n.join(" · ");
|
|
138
|
+
}
|
|
139
|
+
const I = /<\s*(table|thead|tbody|tr|td|th|div|p|span|ul|ol|li|h[1-6]|br)\b/i;
|
|
140
|
+
function O(t) {
|
|
141
|
+
const n = m(t);
|
|
142
|
+
return {
|
|
143
|
+
body: n,
|
|
144
|
+
isHtml: I.test(n)
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function D(t) {
|
|
148
|
+
return t.replace(/<script[\s\S]*?<\/script>/gi, "").replace(/<iframe[\s\S]*?<\/iframe>/gi, "").replace(/\son\w+\s*=\s*(['"])[^'"]*\1/gi, "");
|
|
149
|
+
}
|
|
150
|
+
export {
|
|
151
|
+
a as CITATION_LINK_PREFIX,
|
|
152
|
+
E as citationDisplayNumber,
|
|
153
|
+
p as citationIdToIndex,
|
|
154
|
+
v as countUniqueCitedSources,
|
|
155
|
+
g as detectCitationIdBase,
|
|
156
|
+
_ as extractCitationIdsFromContent,
|
|
157
|
+
R as extractCitationTitle,
|
|
158
|
+
M as formatCitationDocBasename,
|
|
159
|
+
N as formatCitationMeta,
|
|
160
|
+
C as formatCitationPositions,
|
|
161
|
+
A as injectCitationMarkdownLinks,
|
|
162
|
+
$ as normalizeCitation,
|
|
163
|
+
S as parseCitationLinkHref,
|
|
164
|
+
O as prepareCitationContent,
|
|
165
|
+
z as resolveCitationTitle,
|
|
166
|
+
D as sanitizeCitationHtml,
|
|
167
|
+
m as stripCitationFrontmatter
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=citationContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"citationContent.js","sources":["../../../../../src/components/AgentHub/Chat/utils/citationContent.ts"],"sourcesContent":["import type { Citation } from '@/components/AgentHub/types';\n\nexport const CITATION_LINK_PREFIX = '#cite-';\n\n/** RAGFlow / LLM 可能输出的引用标记(单次匹配,避免重复识别) */\nconst CITATION_MARKER_RE =\n /\\[ID[:-](\\d+)\\]|[((]ID[:-](\\d+)[))]|(?<![\\w\\[((])ID[:-](\\d+)(?![\\w])/g;\n\nfunction collectCitationIds(content: string): number[] {\n const ids: number[] = [];\n const re = new RegExp(CITATION_MARKER_RE.source, CITATION_MARKER_RE.flags);\n let match = re.exec(content);\n while (match) {\n const id = match[1] ?? match[2] ?? match[3];\n ids.push(parseInt(id!, 10));\n match = re.exec(content);\n }\n return ids;\n}\n\n/** 从正文中提取所有引用 ID(支持 [ID:n]、(ID:n)、ID:n 等格式) */\nexport function extractCitationIdsFromContent(content: string): number[] {\n return collectCitationIds(content);\n}\n\n/** 正文中实际引用到的来源数量(去重后的 citations 下标) */\nexport function countUniqueCitedSources(content: string, citationsLength: number): number {\n if (citationsLength <= 0) return 0;\n const indices = collectCitationIds(content).map((id) =>\n citationIdToIndex(id, citationsLength, content),\n );\n return new Set(indices).size;\n}\n\n/** 判断 [ID:n] 是 0-based 还是 1-based(RAGFlow 用 0-based,部分 mock/旧数据用 1-based) */\nexport function detectCitationIdBase(content: string, citationsLength: number): 'zero' | 'one' {\n const ids = extractCitationIdsFromContent(content);\n if (ids.length === 0 || citationsLength <= 0) return 'zero';\n\n if (ids.some((id) => id === 0)) return 'zero';\n\n // n === citationsLength 仅 1-based 合法(如 2 条来源时的 [ID:2])\n if (ids.some((id) => id === citationsLength)) return 'one';\n\n const allZeroBasedValid = ids.every((id) => id >= 0 && id < citationsLength);\n const allOneBasedValid = ids.every((id) => id >= 1 && id <= citationsLength);\n\n if (allOneBasedValid && !allZeroBasedValid) return 'one';\n if (allZeroBasedValid && !allOneBasedValid) return 'zero';\n\n const uniqueSorted = [...new Set(ids)].sort((a, b) => a - b);\n if (\n uniqueSorted[0] === 1 &&\n uniqueSorted.length > 0 &&\n uniqueSorted.every((id, i) => id === i + 1)\n ) {\n return 'one';\n }\n\n return 'zero';\n}\n\n/** 将正文中的引用标记转为可自定义渲染的 markdown 链接 */\nexport function injectCitationMarkdownLinks(content: string): string {\n return content.replace(CITATION_MARKER_RE, (_, id1, id2, id3) => {\n const id = id1 ?? id2 ?? id3;\n return `[${id}](${CITATION_LINK_PREFIX}${id})`;\n });\n}\n\nexport function parseCitationLinkHref(href?: string): number | null {\n if (!href?.startsWith(CITATION_LINK_PREFIX)) return null;\n const id = parseInt(href.slice(CITATION_LINK_PREFIX.length), 10);\n return Number.isNaN(id) ? null : id;\n}\n\n/** [ID:n] 映射到 citations 数组下标 */\nexport function citationIdToIndex(id: number, citationsLength: number, content?: string): number {\n if (citationsLength <= 0) return 0;\n const base = content ? detectCitationIdBase(content, citationsLength) : 'zero';\n const index = base === 'one' ? id - 1 : id;\n if (index >= 0 && index < citationsLength) return index;\n return Math.max(0, Math.min(index, citationsLength - 1));\n}\n\n/** 与侧栏 panel 一致的 1-based 展示序号 */\nexport function citationDisplayNumber(\n citationId: number,\n citationsLength: number,\n content?: string,\n): number {\n return citationIdToIndex(citationId, citationsLength, content) + 1;\n}\n\n/** 去掉 RAG chunk 顶部的 YAML frontmatter */\nexport function stripCitationFrontmatter(content: string): string {\n return content.replace(/^\\s*---[\\s\\S]*?---\\s*/m, '').trim();\n}\n\nconst HTML_TAG_ONLY_RE = /^<\\/?[\\w-]+(?:\\s[^>]*)?>$/;\nconst MARKDOWN_TABLE_SEPARATOR_RE = /^\\|?\\s*:?-{3,}/;\n\nconst stripHtmlText = (html: string): string =>\n html\n .replace(/<[^>]+>/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n\nconst isMeaningfulTitle = (text: string): boolean => {\n const trimmed = text.trim();\n if (!trimmed || trimmed.length > 48) return false;\n if (HTML_TAG_ONLY_RE.test(trimmed)) return false;\n if (/^<\\w/.test(trimmed)) return false;\n return true;\n};\n\nconst unwrapParagraphWrapper = (content: string): string =>\n content\n .replace(/^<p[^>]*>/i, '')\n .replace(/<\\/p>$/i, '')\n .trim();\n\nconst extractHtmlTableTitle = (html: string): string | null => {\n const tbodyRow = html.match(/<tbody[^>]*>[\\s\\S]*?<tr[^>]*>[\\s\\S]*?<td[^>]*>([\\s\\S]*?)<\\/td>/i);\n if (tbodyRow?.[1]) {\n const text = stripHtmlText(tbodyRow[1]);\n if (text) return text;\n }\n\n const th = html.match(/<th[^>]*>([\\s\\S]*?)<\\/th>/i);\n if (th?.[1]) {\n const text = stripHtmlText(th[1]);\n if (text) return text;\n }\n\n return null;\n};\n\nconst extractMarkdownTableTitle = (content: string): string | null => {\n const rows: string[][] = [];\n\n content.split('\\n').forEach((line) => {\n const trimmed = line.trim();\n if (!trimmed.includes('|')) return;\n if (MARKDOWN_TABLE_SEPARATOR_RE.test(trimmed.replace(/\\|/g, ''))) return;\n\n const cells = trimmed\n .split('|')\n .map((cell) => cell.trim())\n .filter((cell) => cell.length > 0);\n if (cells.length >= 2) rows.push(cells);\n });\n\n if (rows.length >= 2) return rows[1]?.[0] ?? null;\n if (rows.length === 1) return rows[0]?.[0] ?? null;\n return null;\n};\n\n/** 文档路径取文件名(去扩展名) */\nexport function formatCitationDocBasename(docName?: string): string | undefined {\n if (!docName?.trim()) return undefined;\n\n const normalized = docName.trim().replace(/\\\\/g, '/');\n const basename = normalized.split('/').pop() ?? normalized;\n const withoutExt = basename.replace(/\\.(md|pdf|txt|docx?)$/i, '');\n return withoutExt || basename;\n}\n\n/** 将 RAGFlow chunk 字段归一化为 Citation */\nexport function normalizeCitation(raw: Record<string, unknown>): Citation {\n const docName = raw.doc_name ?? raw.document_name;\n const docId = raw.doc_id ?? raw.document_id;\n const score =\n typeof raw.score === 'number'\n ? raw.score\n : typeof raw.similarity === 'number'\n ? raw.similarity\n : undefined;\n\n let pageNo = raw.page_no as number | null | undefined;\n if (pageNo == null && Array.isArray(raw.positions) && raw.positions.length > 0) {\n const firstPos = raw.positions[0];\n if (Array.isArray(firstPos) && typeof firstPos[0] === 'number' && firstPos[0] > 0) {\n pageNo = firstPos[0];\n }\n }\n\n return {\n id: typeof raw.id === 'string' ? raw.id : String(raw.doc_id ?? raw.document_id ?? Math.random()),\n doc_id: typeof docId === 'string' ? docId : undefined,\n doc_name: typeof docName === 'string' ? docName : undefined,\n dataset_id: typeof raw.dataset_id === 'string' ? raw.dataset_id : undefined,\n content: typeof raw.content === 'string' ? raw.content : undefined,\n score,\n positions: Array.isArray(raw.positions) ? (raw.positions as number[][]) : undefined,\n page_no: pageNo ?? null,\n };\n}\n\n/** 从 chunk 正文提取展示标题 */\nexport function extractCitationTitle(content: string, fallback: string): string {\n const body = stripCitationFrontmatter(content);\n\n const heading = body.match(/^#{1,6}\\s+(.+)$/m);\n if (heading?.[1] && isMeaningfulTitle(heading[1])) return heading[1].trim();\n\n const htmlHeading = body.match(/<h[1-6][^>]*>([\\s\\S]*?)<\\/h[1-6]>/i);\n if (htmlHeading?.[1]) {\n const text = stripHtmlText(htmlHeading[1]);\n if (isMeaningfulTitle(text)) return text;\n }\n\n if (/<table/i.test(body)) {\n const tableTitle = extractHtmlTableTitle(body);\n if (tableTitle && isMeaningfulTitle(tableTitle)) return tableTitle;\n }\n\n const unwrapped = unwrapParagraphWrapper(body);\n if (unwrapped.includes('|')) {\n const tableTitle = extractMarkdownTableTitle(unwrapped);\n if (tableTitle && isMeaningfulTitle(tableTitle)) return tableTitle;\n }\n\n const firstLine = body\n .split('\\n')\n .map((line) => stripHtmlText(line.trim()))\n .find((line) => line.length > 0 && !line.startsWith('|') && isMeaningfulTitle(line));\n if (firstLine) return firstLine;\n\n return fallback;\n}\n\n/** 引用侧栏标题:展示 document_name */\nexport function resolveCitationTitle(citation: Citation, index: number): string {\n return citation.doc_name?.trim() || `来源 ${index + 1}`;\n}\n\n/** 格式化 chunk positions(RAGFlow: [页码, left, right, top, bottom]) */\nexport function formatCitationPositions(positions?: unknown): string | undefined {\n const pos = positions as number[][] | undefined;\n if (!pos?.length) return undefined;\n\n const first = pos[0];\n if (!first?.length) return undefined;\n\n const page = first[0];\n if (typeof page === 'number' && page > 0) {\n return `第 ${page} 页`;\n }\n\n return `位置 ${first.join(', ')}`;\n}\n\n/** 引用侧栏元信息:positions · 匹配度 */\nexport function formatCitationMeta(citation: Citation): string {\n const parts: string[] = [];\n const positionLabel = formatCitationPositions(citation.positions);\n if (positionLabel) parts.push(positionLabel);\n if (citation.score !== undefined) parts.push(`匹配 ${(citation.score * 100).toFixed(0)}%`);\n return parts.join(' · ');\n}\n\nexport interface PreparedCitationContent {\n body: string;\n isHtml: boolean;\n}\n\nconst HTML_CONTENT_PATTERN = /<\\s*(table|thead|tbody|tr|td|th|div|p|span|ul|ol|li|h[1-6]|br)\\b/i;\n\n/** 预处理引用正文,供 Markdown / HTML 分支渲染 */\nexport function prepareCitationContent(content: string): PreparedCitationContent {\n const body = stripCitationFrontmatter(content);\n return {\n body,\n isHtml: HTML_CONTENT_PATTERN.test(body),\n };\n}\n\n/** 引用 HTML 仅做基础清理(内容来自可信 RAG 知识库) */\nexport function sanitizeCitationHtml(html: string): string {\n return html\n .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n .replace(/<iframe[\\s\\S]*?<\\/iframe>/gi, '')\n .replace(/\\son\\w+\\s*=\\s*(['\"])[^'\"]*\\1/gi, '');\n}\n"],"names":["CITATION_LINK_PREFIX","CITATION_MARKER_RE","collectCitationIds","content","ids","re","match","id","extractCitationIdsFromContent","countUniqueCitedSources","citationsLength","indices","citationIdToIndex","detectCitationIdBase","allZeroBasedValid","allOneBasedValid","uniqueSorted","a","b","i","injectCitationMarkdownLinks","_","id1","id2","id3","parseCitationLinkHref","href","index","citationDisplayNumber","citationId","stripCitationFrontmatter","HTML_TAG_ONLY_RE","MARKDOWN_TABLE_SEPARATOR_RE","stripHtmlText","html","isMeaningfulTitle","text","trimmed","unwrapParagraphWrapper","extractHtmlTableTitle","tbodyRow","th","extractMarkdownTableTitle","_a","_b","rows","line","cells","cell","formatCitationDocBasename","docName","normalized","basename","normalizeCitation","raw","docId","score","pageNo","firstPos","extractCitationTitle","fallback","body","heading","htmlHeading","tableTitle","unwrapped","firstLine","resolveCitationTitle","citation","formatCitationPositions","positions","pos","first","page","formatCitationMeta","parts","positionLabel","HTML_CONTENT_PATTERN","prepareCitationContent","sanitizeCitationHtml"],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
const h = "<think>", m = "</think>", p = new RegExp(
|
|
2
|
+
h.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "([\\s\\S]*?)" + m.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"),
|
|
3
|
+
"gi"
|
|
4
|
+
), c = /<\/?think>/gi;
|
|
5
|
+
function t(n) {
|
|
6
|
+
return n.replace(/\n{3,}/g, `
|
|
7
|
+
|
|
8
|
+
`).trimEnd();
|
|
9
|
+
}
|
|
10
|
+
const u = /\[ID[:-]\d+\]/;
|
|
11
|
+
function T(n) {
|
|
12
|
+
if (!n) return n;
|
|
13
|
+
let i = n.replace(/\r\n/g, `
|
|
14
|
+
`);
|
|
15
|
+
return i = i.replace(/```\s*mermaid[ \t]*(?!\n)/gi, "```mermaid\n"), i = i.replace(
|
|
16
|
+
/```mermaid\n([\s\S]*?)(\n(?:风格说明|Style)[^\n`]*[\s\S]*?)(?=```|$)/gi,
|
|
17
|
+
(o, r, s) => `\`\`\`mermaid
|
|
18
|
+
${r.trimEnd()}
|
|
19
|
+
\`\`\`
|
|
20
|
+
${s.trim()}`
|
|
21
|
+
), i;
|
|
22
|
+
}
|
|
23
|
+
function d(n) {
|
|
24
|
+
return u.test(n);
|
|
25
|
+
}
|
|
26
|
+
function w(n, i = !1) {
|
|
27
|
+
var g;
|
|
28
|
+
if (!n)
|
|
29
|
+
return { thinking: "", answer: "", isThinking: i };
|
|
30
|
+
const o = n.toLowerCase(), r = o.lastIndexOf(m), s = o.lastIndexOf(h), a = [];
|
|
31
|
+
for (const e of n.matchAll(p)) {
|
|
32
|
+
const l = (g = e[1]) == null ? void 0 : g.trim();
|
|
33
|
+
l && a.push(l);
|
|
34
|
+
}
|
|
35
|
+
if (i && r === -1)
|
|
36
|
+
return {
|
|
37
|
+
thinking: t(n.replace(c, "").trim()),
|
|
38
|
+
answer: "",
|
|
39
|
+
isThinking: !0
|
|
40
|
+
};
|
|
41
|
+
if (s > r) {
|
|
42
|
+
const e = n.slice(0, s).replace(c, "").trim(), l = n.slice(s + h.length).replace(c, "").trim(), k = [
|
|
43
|
+
...e ? [e] : [],
|
|
44
|
+
...a,
|
|
45
|
+
...l ? [l] : []
|
|
46
|
+
].join(`
|
|
47
|
+
|
|
48
|
+
`);
|
|
49
|
+
return {
|
|
50
|
+
thinking: t(k),
|
|
51
|
+
answer: "",
|
|
52
|
+
isThinking: i
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (r !== -1) {
|
|
56
|
+
const e = t(
|
|
57
|
+
n.slice(r + m.length).replace(c, "").trim()
|
|
58
|
+
);
|
|
59
|
+
if (e)
|
|
60
|
+
return {
|
|
61
|
+
thinking: t(a.join(`
|
|
62
|
+
|
|
63
|
+
`)),
|
|
64
|
+
answer: e,
|
|
65
|
+
isThinking: !1
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const f = t(
|
|
69
|
+
n.replace(p, "").replace(c, "").trim()
|
|
70
|
+
);
|
|
71
|
+
return {
|
|
72
|
+
thinking: t(a.join(`
|
|
73
|
+
|
|
74
|
+
`)),
|
|
75
|
+
answer: f,
|
|
76
|
+
isThinking: !1
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
d as hasCitationMarkers,
|
|
81
|
+
T as normalizeAssistantMarkdown,
|
|
82
|
+
t as normalizeDisplayText,
|
|
83
|
+
w as parseAssistantContent
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=messageContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messageContent.js","sources":["../../../../../src/components/AgentHub/Chat/utils/messageContent.ts"],"sourcesContent":["const THINK_OPEN = '<' + 'think>';\nconst THINK_CLOSE = '<' + '/think>';\nconst THINK_BLOCK_RE = new RegExp(\n THINK_OPEN.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&') +\n '([\\\\s\\\\S]*?)' +\n THINK_CLOSE.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'),\n 'gi',\n);\nconst THINK_TAG_RE = /<\\/?think>/gi;\n\nexport interface ParsedAssistantContent {\n /** Reasoning text extracted from think blocks */\n thinking: string;\n /** User-facing answer (outside think blocks) */\n answer: string;\n /** Stream still inside an unclosed think block */\n isThinking: boolean;\n}\n\n/** Collapse excessive blank lines and trim trailing whitespace for display */\nexport function normalizeDisplayText(text: string): string {\n return text.replace(/\\n{3,}/g, '\\n\\n').trimEnd();\n}\n\nconst CITATION_MARKER_TEST_RE = /\\[ID[:-]\\d+\\]/;\n\n/** Normalize assistant markdown from persisted sessions (fences, mermaid blocks). */\nexport function normalizeAssistantMarkdown(content: string): string {\n if (!content) return content;\n\n let text = content.replace(/\\r\\n/g, '\\n');\n\n // Ensure newline after ```mermaid opening fence\n text = text.replace(/```\\s*mermaid[ \\t]*(?!\\n)/gi, '```mermaid\\n');\n\n // Move trailing prose after mermaid block out of the fence when closing ``` is missing\n text = text.replace(\n /```mermaid\\n([\\s\\S]*?)(\\n(?:风格说明|Style)[^\\n`]*[\\s\\S]*?)(?=```|$)/gi,\n (_, chart, prose) => {\n const trimmedChart = chart.trimEnd();\n return `\\`\\`\\`mermaid\\n${trimmedChart}\\n\\`\\`\\`\\n${prose.trim()}`;\n },\n );\n\n return text;\n}\n\nexport function hasCitationMarkers(content: string): boolean {\n return CITATION_MARKER_TEST_RE.test(content);\n}\n\n/**\n * Split assistant output into hidden reasoning and visible answer.\n * RAGFlow / reasoning models may wrap chain-of-thought in think tags.\n */\nexport function parseAssistantContent(content: string, streaming = false): ParsedAssistantContent {\n if (!content) {\n return { thinking: '', answer: '', isThinking: streaming };\n }\n\n const lower = content.toLowerCase();\n const lastClose = lower.lastIndexOf(THINK_CLOSE);\n const lastOpen = lower.lastIndexOf(THINK_OPEN);\n\n const thinkingParts: string[] = [];\n for (const match of content.matchAll(THINK_BLOCK_RE)) {\n const part = match[1]?.trim();\n if (part) thinkingParts.push(part);\n }\n\n // Streaming: before arrives, treat all output as reasoning\n if (streaming && lastClose === -1) {\n return {\n thinking: normalizeDisplayText(content.replace(THINK_TAG_RE, '').trim()),\n answer: '',\n isThinking: true,\n };\n }\n\n // Streaming: unclosed think block at the end\n if (lastOpen > lastClose) {\n const beforeOpen = content.slice(0, lastOpen).replace(THINK_TAG_RE, '').trim();\n const insideThink = content\n .slice(lastOpen + THINK_OPEN.length)\n .replace(THINK_TAG_RE, '')\n .trim();\n const thinking = [\n ...(beforeOpen ? [beforeOpen] : []),\n ...thinkingParts,\n ...(insideThink ? [insideThink] : []),\n ].join('\\n\\n');\n\n return {\n thinking: normalizeDisplayText(thinking),\n answer: '',\n isThinking: streaming,\n };\n }\n\n // Prefer final answer after the last closing think tag\n if (lastClose !== -1) {\n const answer = normalizeDisplayText(\n content\n .slice(lastClose + THINK_CLOSE.length)\n .replace(THINK_TAG_RE, '')\n .trim(),\n );\n if (answer) {\n return {\n thinking: normalizeDisplayText(thinkingParts.join('\\n\\n')),\n answer,\n isThinking: false,\n };\n }\n }\n\n const answer = normalizeDisplayText(\n content.replace(THINK_BLOCK_RE, '').replace(THINK_TAG_RE, '').trim(),\n );\n\n return {\n thinking: normalizeDisplayText(thinkingParts.join('\\n\\n')),\n answer,\n isThinking: false,\n };\n}\n"],"names":["THINK_OPEN","THINK_CLOSE","THINK_BLOCK_RE","THINK_TAG_RE","normalizeDisplayText","text","CITATION_MARKER_TEST_RE","normalizeAssistantMarkdown","content","_","chart","prose","hasCitationMarkers","parseAssistantContent","streaming","_a","lower","lastClose","lastOpen","thinkingParts","match","part","beforeOpen","insideThink","thinking","answer"],"mappings":"AAAA,MAAMA,IAAa,WACbC,IAAc,YACdC,IAAiB,IAAI;AAAA,EACzBF,EAAW,QAAQ,uBAAuB,MAAM,IAC9C,iBACAC,EAAY,QAAQ,uBAAuB,MAAM;AAAA,EACnD;AACF,GACME,IAAe;AAYd,SAASC,EAAqBC,GAAsB;AACzD,SAAOA,EAAK,QAAQ,WAAW;AAAA;AAAA,CAAM,EAAE,QAAA;AACzC;AAEA,MAAMC,IAA0B;AAGzB,SAASC,EAA2BC,GAAyB;AAClE,MAAI,CAACA,EAAS,QAAOA;AAErB,MAAIH,IAAOG,EAAQ,QAAQ,SAAS;AAAA,CAAI;AAGxC,SAAAH,IAAOA,EAAK,QAAQ,+BAA+B,cAAc,GAGjEA,IAAOA,EAAK;AAAA,IACV;AAAA,IACA,CAACI,GAAGC,GAAOC,MAEF;AAAA,EADcD,EAAM,QAAA,CACU;AAAA;AAAA,EAAaC,EAAM,MAAM;AAAA,EAChE,GAGKN;AACT;AAEO,SAASO,EAAmBJ,GAA0B;AAC3D,SAAOF,EAAwB,KAAKE,CAAO;AAC7C;AAMO,SAASK,EAAsBL,GAAiBM,IAAY,IAA+B;AAvDlG,MAAAC;AAwDE,MAAI,CAACP;AACH,WAAO,EAAE,UAAU,IAAI,QAAQ,IAAI,YAAYM,EAAA;AAGjD,QAAME,IAAQR,EAAQ,YAAA,GAChBS,IAAYD,EAAM,YAAYf,CAAW,GACzCiB,IAAWF,EAAM,YAAYhB,CAAU,GAEvCmB,IAA0B,CAAA;AAChC,aAAWC,KAASZ,EAAQ,SAASN,CAAc,GAAG;AACpD,UAAMmB,KAAON,IAAAK,EAAM,CAAC,MAAP,gBAAAL,EAAU;AACvB,IAAIM,KAAMF,EAAc,KAAKE,CAAI;AAAA,EACnC;AAGA,MAAIP,KAAaG,MAAc;AAC7B,WAAO;AAAA,MACL,UAAUb,EAAqBI,EAAQ,QAAQL,GAAc,EAAE,EAAE,MAAM;AAAA,MACvE,QAAQ;AAAA,MACR,YAAY;AAAA,IAAA;AAKhB,MAAIe,IAAWD,GAAW;AACxB,UAAMK,IAAad,EAAQ,MAAM,GAAGU,CAAQ,EAAE,QAAQf,GAAc,EAAE,EAAE,KAAA,GAClEoB,IAAcf,EACjB,MAAMU,IAAWlB,EAAW,MAAM,EAClC,QAAQG,GAAc,EAAE,EACxB,KAAA,GACGqB,IAAW;AAAA,MACf,GAAIF,IAAa,CAACA,CAAU,IAAI,CAAA;AAAA,MAChC,GAAGH;AAAA,MACH,GAAII,IAAc,CAACA,CAAW,IAAI,CAAA;AAAA,IAAC,EACnC,KAAK;AAAA;AAAA,CAAM;AAEb,WAAO;AAAA,MACL,UAAUnB,EAAqBoB,CAAQ;AAAA,MACvC,QAAQ;AAAA,MACR,YAAYV;AAAA,IAAA;AAAA,EAEhB;AAGA,MAAIG,MAAc,IAAI;AACpB,UAAMQ,IAASrB;AAAA,MACbI,EACG,MAAMS,IAAYhB,EAAY,MAAM,EACpC,QAAQE,GAAc,EAAE,EACxB,KAAA;AAAA,IAAK;AAEV,QAAIsB;AACF,aAAO;AAAA,QACL,UAAUrB,EAAqBe,EAAc,KAAK;AAAA;AAAA,CAAM,CAAC;AAAA,QACzD,QAAAM;AAAAA,QACA,YAAY;AAAA,MAAA;AAAA,EAGlB;AAEA,QAAMA,IAASrB;AAAA,IACbI,EAAQ,QAAQN,GAAgB,EAAE,EAAE,QAAQC,GAAc,EAAE,EAAE,KAAA;AAAA,EAAK;AAGrE,SAAO;AAAA,IACL,UAAUC,EAAqBe,EAAc,KAAK;AAAA;AAAA,CAAM,CAAC;AAAA,IACzD,QAAAM;AAAA,IACA,YAAY;AAAA,EAAA;AAEhB;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const a = /[(),():;#]/, u = /^(graph|flowchart|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap|timeline|gitGraph|C4Context|subgraph|end|style|classDef|class|linkStyle|click|direction|%%)/i, c = /(-->|---|-\.->|==>|===|-\.-)/;
|
|
2
|
+
function m(e) {
|
|
3
|
+
return e.split(`
|
|
4
|
+
`).filter((r) => {
|
|
5
|
+
const t = r.trim();
|
|
6
|
+
return !!(!t || u.test(t) || c.test(t) || /^[A-Za-z0-9_]+[\[\{(]/.test(t) || /^[A-Za-z0-9_[\](){}<>"'\\.:;+\-/%&|=\s]+$/.test(t));
|
|
7
|
+
}).join(`
|
|
8
|
+
`).trim();
|
|
9
|
+
}
|
|
10
|
+
function n(e) {
|
|
11
|
+
const r = e.trim();
|
|
12
|
+
return !r || r.startsWith('"') || r.startsWith("'") || !a.test(r) ? e : `"${r.replace(/"/g, '\\"')}"`;
|
|
13
|
+
}
|
|
14
|
+
function o(e) {
|
|
15
|
+
let t = m(e).replace(/\[([^\]"]+)\]/g, (s, i) => `[${n(i)}]`);
|
|
16
|
+
return t = t.replace(/\{([^}"]+)\}/g, (s, i) => `{${n(i)}}`), t;
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
o as sanitizeMermaidChart,
|
|
20
|
+
m as stripProseFromMermaid
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=sanitizeMermaidChart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizeMermaidChart.js","sources":["../../../../../src/components/AgentHub/Chat/utils/sanitizeMermaidChart.ts"],"sourcesContent":["/** Characters inside node labels that require double-quoting in Mermaid. */\nconst LABEL_NEEDS_QUOTING_RE = /[(),():;#]/;\n\n/** Fix AI-generated Mermaid blocks: quote labels, drop prose lines mistakenly inside the chart. */\nconst MERMAID_LINE_RE =\n /^(graph|flowchart|sequenceDiagram|classDiagram|stateDiagram|erDiagram|gantt|pie|mindmap|timeline|gitGraph|C4Context|subgraph|end|style|classDef|class|linkStyle|click|direction|%%)/i;\nconst MERMAID_EDGE_RE = /(-->|---|-\\.->|==>|===|-\\.-)/;\n\n/** Remove non-Mermaid prose lines (e.g. 风格说明) that LLMs append inside code blocks. */\nexport function stripProseFromMermaid(chart: string): string {\n return chart\n .split('\\n')\n .filter((line) => {\n const trimmed = line.trim();\n if (!trimmed) return true;\n if (MERMAID_LINE_RE.test(trimmed)) return true;\n if (MERMAID_EDGE_RE.test(trimmed)) return true;\n if (/^[A-Za-z0-9_]+[\\[\\{(]/.test(trimmed)) return true;\n if (/^[A-Za-z0-9_[\\](){}<>\"'\\\\.:;+\\-/%&|=\\s]+$/.test(trimmed)) return true;\n return false;\n })\n .join('\\n')\n .trim();\n}\n\nfunction quoteLabelContent(label: string): string {\n const trimmed = label.trim();\n if (!trimmed || trimmed.startsWith('\"') || trimmed.startsWith(\"'\")) {\n return label;\n }\n if (!LABEL_NEEDS_QUOTING_RE.test(trimmed)) {\n return label;\n }\n return `\"${trimmed.replace(/\"/g, '\\\\\"')}\"`;\n}\n\n/**\n * Fix common AI-generated Mermaid syntax issues before rendering.\n * e.g. C[梳理(生條)] → C[\"梳理(生條)\"]\n */\nexport function sanitizeMermaidChart(chart: string): string {\n const stripped = stripProseFromMermaid(chart);\n let result = stripped.replace(/\\[([^\\]\"]+)\\]/g, (_match, label: string) => {\n return `[${quoteLabelContent(label)}]`;\n });\n\n result = result.replace(/\\{([^}\"]+)\\}/g, (_match, label: string) => {\n return `{${quoteLabelContent(label)}}`;\n });\n\n return result;\n}\n"],"names":["LABEL_NEEDS_QUOTING_RE","MERMAID_LINE_RE","MERMAID_EDGE_RE","stripProseFromMermaid","chart","line","trimmed","quoteLabelContent","label","sanitizeMermaidChart","result","_match"],"mappings":"AACA,MAAMA,IAAyB,cAGzBC,IACJ,wLACIC,IAAkB;AAGjB,SAASC,EAAsBC,GAAuB;AAC3D,SAAOA,EACJ,MAAM;AAAA,CAAI,EACV,OAAO,CAACC,MAAS;AAChB,UAAMC,IAAUD,EAAK,KAAA;AAKrB,WAJI,IAACC,KACDL,EAAgB,KAAKK,CAAO,KAC5BJ,EAAgB,KAAKI,CAAO,KAC5B,wBAAwB,KAAKA,CAAO,KACpC,4CAA4C,KAAKA,CAAO;AAAA,EAE9D,CAAC,EACA,KAAK;AAAA,CAAI,EACT,KAAA;AACL;AAEA,SAASC,EAAkBC,GAAuB;AAChD,QAAMF,IAAUE,EAAM,KAAA;AAItB,SAHI,CAACF,KAAWA,EAAQ,WAAW,GAAG,KAAKA,EAAQ,WAAW,GAAG,KAG7D,CAACN,EAAuB,KAAKM,CAAO,IAC/BE,IAEF,IAAIF,EAAQ,QAAQ,MAAM,KAAK,CAAC;AACzC;AAMO,SAASG,EAAqBL,GAAuB;AAE1D,MAAIM,IADaP,EAAsBC,CAAK,EACtB,QAAQ,kBAAkB,CAACO,GAAQH,MAChD,IAAID,EAAkBC,CAAK,CAAC,GACpC;AAED,SAAAE,IAASA,EAAO,QAAQ,iBAAiB,CAACC,GAAQH,MACzC,IAAID,EAAkBC,CAAK,CAAC,GACpC,GAEME;AACT;"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { normalizeCitation as h } from "./citationContent.js";
|
|
2
|
+
import { hasCitationMarkers as p } from "./messageContent.js";
|
|
3
|
+
const S = /* @__PURE__ */ new Set(["New session", "新会话"]), d = /^\d{1,4}$/, E = (e) => {
|
|
4
|
+
if (e == null) return "";
|
|
5
|
+
const t = new Date(typeof e == "number" && e < 1e12 ? e * 1e3 : e);
|
|
6
|
+
if (Number.isNaN(t.getTime())) return "";
|
|
7
|
+
const n = /* @__PURE__ */ new Date();
|
|
8
|
+
return t.getFullYear() === n.getFullYear() && t.getMonth() === n.getMonth() && t.getDate() === n.getDate() ? t.toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" }) : t.toLocaleString("zh-CN", {
|
|
9
|
+
month: "2-digit",
|
|
10
|
+
day: "2-digit",
|
|
11
|
+
hour: "2-digit",
|
|
12
|
+
minute: "2-digit"
|
|
13
|
+
});
|
|
14
|
+
}, y = (e) => {
|
|
15
|
+
if (e == null) return "";
|
|
16
|
+
if (typeof e == "string") return e;
|
|
17
|
+
if (typeof e == "number" || typeof e == "boolean") return String(e);
|
|
18
|
+
if (Array.isArray(e))
|
|
19
|
+
return e.map((t) => {
|
|
20
|
+
if (typeof t == "string") return t;
|
|
21
|
+
if (t && typeof t == "object") {
|
|
22
|
+
const n = t;
|
|
23
|
+
if (typeof n.text == "string") return n.text;
|
|
24
|
+
if (typeof n.content == "string") return n.content;
|
|
25
|
+
}
|
|
26
|
+
return "";
|
|
27
|
+
}).filter(Boolean).join(`
|
|
28
|
+
`);
|
|
29
|
+
if (typeof e == "object") {
|
|
30
|
+
const t = e;
|
|
31
|
+
if (typeof t.text == "string") return t.text;
|
|
32
|
+
if (typeof t.content == "string") return t.content;
|
|
33
|
+
if (typeof t.answer == "string") return t.answer;
|
|
34
|
+
}
|
|
35
|
+
return "";
|
|
36
|
+
}, f = (e) => {
|
|
37
|
+
const t = e.created_at ?? e.create_time;
|
|
38
|
+
return typeof t == "number" ? t : void 0;
|
|
39
|
+
}, b = (e) => {
|
|
40
|
+
const t = e.filter((n) => f(n) != null);
|
|
41
|
+
return t.length < 2 || t.length < e.length ? e : [...e].sort((n, r) => {
|
|
42
|
+
const i = f(n), o = f(r);
|
|
43
|
+
return i - o;
|
|
44
|
+
});
|
|
45
|
+
}, w = (e) => {
|
|
46
|
+
const t = e.trim();
|
|
47
|
+
return t ? !/[\S\u4e00-\u9fff]/.test(t) : !0;
|
|
48
|
+
}, D = (e) => {
|
|
49
|
+
var o;
|
|
50
|
+
const t = (o = e.name) == null ? void 0 : o.trim();
|
|
51
|
+
if (t && !S.has(t))
|
|
52
|
+
return t;
|
|
53
|
+
const r = (e.messages ?? e.message ?? []).find((s) => s.role === "user"), i = y(r == null ? void 0 : r.content).trim();
|
|
54
|
+
return i ? i.length > 24 ? `${i.slice(0, 24)}…` : i : "新会话";
|
|
55
|
+
}, M = (e, t) => {
|
|
56
|
+
var r;
|
|
57
|
+
if (e.length === 0) return !0;
|
|
58
|
+
if (e.length !== 1 || ((r = e[0]) == null ? void 0 : r.role) !== "assistant") return !1;
|
|
59
|
+
const n = e[0].content.trim();
|
|
60
|
+
return n ? t != null && t.trim() ? n === t.trim() : !1 : !0;
|
|
61
|
+
}, g = (e) => {
|
|
62
|
+
const t = /* @__PURE__ */ new Set();
|
|
63
|
+
return e.filter((n) => {
|
|
64
|
+
var i;
|
|
65
|
+
const r = `${n.doc_id ?? ""}:${n.id ?? ""}:${((i = n.content) == null ? void 0 : i.slice(0, 80)) ?? ""}`;
|
|
66
|
+
return t.has(r) ? !1 : (t.add(r), !0);
|
|
67
|
+
});
|
|
68
|
+
}, m = (e) => Array.isArray(e) ? e.filter((t) => t && typeof t == "object").map((t) => h(t)) : e && typeof e == "object" ? Object.values(e).filter((t) => t && typeof t == "object").map((t) => h(t)) : [], a = (e) => {
|
|
69
|
+
if (e == null) return;
|
|
70
|
+
if (Array.isArray(e)) {
|
|
71
|
+
const n = m(e);
|
|
72
|
+
return n.length > 0 ? g(n) : void 0;
|
|
73
|
+
}
|
|
74
|
+
if (typeof e != "object" || !("chunks" in e))
|
|
75
|
+
return;
|
|
76
|
+
const t = m(e.chunks);
|
|
77
|
+
return t.length > 0 ? g(t) : void 0;
|
|
78
|
+
}, C = (e) => {
|
|
79
|
+
const t = [];
|
|
80
|
+
return e.forEach((n) => {
|
|
81
|
+
const r = a(n);
|
|
82
|
+
r && t.push(...r);
|
|
83
|
+
}), g(t);
|
|
84
|
+
}, N = (e, t) => e.slice(0, t).filter((n) => n.role === "user").length, T = (e, t, n, r, i, o) => {
|
|
85
|
+
if (e.role !== "assistant") return;
|
|
86
|
+
const s = a(e.reference);
|
|
87
|
+
if (s != null && s.length) return s;
|
|
88
|
+
const u = N(n, t);
|
|
89
|
+
if (u === 0) return;
|
|
90
|
+
const c = a(r[t]);
|
|
91
|
+
if (c != null && c.length) return c;
|
|
92
|
+
const l = a(r[u - 1]);
|
|
93
|
+
if (l != null && l.length) return l;
|
|
94
|
+
if (p(o) && i.length)
|
|
95
|
+
return i;
|
|
96
|
+
}, $ = (e = [], t = []) => {
|
|
97
|
+
const n = C(t), r = b(e);
|
|
98
|
+
return r.filter((i) => i.role === "user" || i.role === "assistant").map((i, o) => {
|
|
99
|
+
const s = y(i.content);
|
|
100
|
+
return {
|
|
101
|
+
id: i.id ?? `msg_${o}_${i.role}`,
|
|
102
|
+
role: i.role,
|
|
103
|
+
content: s,
|
|
104
|
+
citations: T(
|
|
105
|
+
i,
|
|
106
|
+
o,
|
|
107
|
+
r,
|
|
108
|
+
t,
|
|
109
|
+
n,
|
|
110
|
+
s
|
|
111
|
+
),
|
|
112
|
+
thumbup: typeof i.thumbup == "boolean" ? i.thumbup : void 0
|
|
113
|
+
};
|
|
114
|
+
}).filter((i) => !w(i.content));
|
|
115
|
+
}, _ = (e, t) => {
|
|
116
|
+
var i, o, s, u;
|
|
117
|
+
if (!(t != null && t.trim()) || e.length === 0) return e;
|
|
118
|
+
const n = t.trim();
|
|
119
|
+
let r = [...e];
|
|
120
|
+
for (; r.length > 0 && ((i = r[0]) == null ? void 0 : i.role) === "assistant" && ((o = r[0]) == null ? void 0 : o.content.trim()) === n; )
|
|
121
|
+
r = r.slice(1);
|
|
122
|
+
for (; r.length > 1 && ((s = r[r.length - 1]) == null ? void 0 : s.role) === "assistant" && ((u = r[r.length - 1]) == null ? void 0 : u.content.trim()) === n; )
|
|
123
|
+
r = r.slice(0, -1);
|
|
124
|
+
return r;
|
|
125
|
+
}, A = (e) => {
|
|
126
|
+
const t = /* @__PURE__ */ new Map();
|
|
127
|
+
e.forEach((r) => {
|
|
128
|
+
if (r.role !== "user") return;
|
|
129
|
+
const i = r.content.trim();
|
|
130
|
+
d.test(i) && t.set(i, (t.get(i) ?? 0) + 1);
|
|
131
|
+
});
|
|
132
|
+
const n = new Set(
|
|
133
|
+
[...t.entries()].filter(([, r]) => r > 1).map(([r]) => r)
|
|
134
|
+
);
|
|
135
|
+
return n.size === 0 ? e : e.filter(
|
|
136
|
+
(r) => !(r.role === "user" && n.has(r.content.trim()) && d.test(r.content.trim()))
|
|
137
|
+
);
|
|
138
|
+
}, U = (e, t) => {
|
|
139
|
+
const n = _(e, t), r = A(n);
|
|
140
|
+
return r.some((i) => i.role === "user") ? M(r, t) ? [] : r : [];
|
|
141
|
+
};
|
|
142
|
+
export {
|
|
143
|
+
a as extractCitations,
|
|
144
|
+
E as formatSessionTime,
|
|
145
|
+
D as getSessionDisplayName,
|
|
146
|
+
M as isWelcomeOnlyMessages,
|
|
147
|
+
y as normalizeMessageContent,
|
|
148
|
+
$ as parseSessionMessages,
|
|
149
|
+
U as toDisplayMessages
|
|
150
|
+
};
|
|
151
|
+
//# sourceMappingURL=sessionMessages.js.map
|