@fv-ui/ai-chat 0.5.0 → 0.7.0

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 CHANGED
@@ -437,6 +437,8 @@ Markdown 渲染(Sanitized by DOMPurify),内置 Prism 代码高亮与 KaTeX。
437
437
  | title | string | '' | 顶栏标题(同时作空态欢迎页名称) |
438
438
  | showHeader | boolean | false | 显示顶栏(标题 + 模型选择器;models 多选选择器在顶栏内,需开启才可见) |
439
439
  | centerWelcome | boolean | true | 空态居中:未开始对话时欢迎内容与输入区整体垂直居中,首条消息后输入区恢复固定底部 |
440
+ | showScrollButton | boolean | true | 显示滚到底部悬浮按钮(透传 AiMessages;距底超过 scrollButtonThreshold 时出现) |
441
+ | scrollButtonThreshold | number | 100 | 滚到底部悬浮按钮显示阈值(px,透传 AiMessages) |
440
442
  | showUserAvatar | boolean | true | 显示用户头像(false 时用户消息不渲染头像;助手头像不受影响) |
441
443
  | showUserName | boolean | true | 显示用户名称(false 时用户消息不渲染头部名称行;助手名称不受影响) |
442
444
  | showAssistantAvatar | boolean | true | 显示助手头像(false 时助手消息不渲染头像;用户头像不受影响) |
@@ -471,6 +473,8 @@ Markdown 渲染(Sanitized by DOMPurify),内置 Prism 代码高亮与 KaTeX。
471
473
  | user-avatar / assistant-avatar | 自定义用户/助手头像(无作用域,优先于同名 props) |
472
474
  | user-name / assistant-name | 自定义用户/助手名称(作用域 { message },优先于同名 props) |
473
475
  | empty | 覆盖空态整区 |
476
+ | scroll-button | 自定义滚到底部悬浮按钮整块(作用域 { scrollToBottom, awayFromBottom };覆盖后内置按钮与显隐逻辑均由插槽内容接管) |
477
+ | scroll-button-icon | 仅自定义悬浮按钮图标内容(按钮本体/显隐不变) |
474
478
  | sender-prefix | 输入区前缀 |
475
479
 
476
480
  | Ref | 说明 |
@@ -497,6 +501,8 @@ Markdown 渲染(Sanitized by DOMPurify),内置 Prism 代码高亮与 KaTeX。
497
501
  | suggestions | AiMessagesSuggestion[] | [] | 空态建议列表 |
498
502
  | suggestionsTitle | string | '' | 空态建议区标题 |
499
503
  | scrollThreshold | number | 40 | 吸底阈值(px):距底不超过该值才自动跟随 |
504
+ | showScrollButton | boolean | true | 显示滚到底部悬浮按钮(空态不渲染) |
505
+ | scrollButtonThreshold | number | 100 | 距底超过该值(px)才显示滚到底部悬浮按钮 |
500
506
  | showActions | boolean | true | 显示消息操作按钮(复制/重生成) |
501
507
  | showBranchSwitch | boolean | true | 显示分支切换器 |
502
508
  | showUserAvatar | boolean | true | 显示用户头像(助手头像不受影响) |
@@ -515,6 +521,8 @@ Markdown 渲染(Sanitized by DOMPurify),内置 Prism 代码高亮与 KaTeX。
515
521
  | Slot | 说明 |
516
522
  | --- | --- |
517
523
  | empty | 覆盖空态整区 |
524
+ | scroll-button | 自定义滚到底部悬浮按钮整块(作用域 { scrollToBottom, awayFromBottom };覆盖后内置按钮与显隐逻辑均由插槽内容接管) |
525
+ | scroll-button-icon | 仅自定义悬浮按钮图标内容(按钮本体/显隐不变) |
518
526
  | message-avatar / message-actions | 透传给每条 AiMessage(message-avatar 优先于细分头像插槽) |
519
527
  | user-avatar / assistant-avatar | 自定义用户/助手头像(无作用域,优先于同名 props) |
520
528
  | user-name / assistant-name | 自定义用户/助手名称(作用域 { message },优先于同名 props) |
package/dist/index.d.ts CHANGED
@@ -369,7 +369,7 @@ declare function closeHeader$2(): void;
369
369
  declare var __VLS_1$8: {};
370
370
  declare var __VLS_3$3: {};
371
371
  declare var __VLS_5: {};
372
- declare var __VLS_52$1: {
372
+ declare var __VLS_52: {
373
373
  keyword: string;
374
374
  };
375
375
  declare var __VLS_54: {};
@@ -382,7 +382,7 @@ type __VLS_Slots$c = {} & {
382
382
  } & {
383
383
  prefix?: (props: typeof __VLS_5) => any;
384
384
  } & {
385
- trigger?: (props: typeof __VLS_52$1) => any;
385
+ trigger?: (props: typeof __VLS_52) => any;
386
386
  } & {
387
387
  'action-list'?: (props: typeof __VLS_54) => any;
388
388
  } & {
@@ -876,12 +876,12 @@ type __VLS_Props$9 = {
876
876
  /** 排列方向:vertical 纵向(带连接线)/ horizontal 横向 */
877
877
  direction?: 'vertical' | 'horizontal';
878
878
  };
879
- declare var __VLS_45: {
879
+ declare var __VLS_45$1: {
880
880
  item: ThoughtChainItem;
881
881
  index: number;
882
882
  };
883
883
  type __VLS_Slots$8 = {} & {
884
- content?: (props: typeof __VLS_45) => any;
884
+ content?: (props: typeof __VLS_45$1) => any;
885
885
  };
886
886
  declare const __VLS_base$8: vue.DefineComponent<__VLS_Props$9, {}, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<__VLS_Props$9> & Readonly<{}>, {
887
887
  items: ThoughtChainItem[];
@@ -1392,6 +1392,20 @@ interface ChatFile {
1392
1392
  /** 附件类别,缺省按 'file' 处理 */
1393
1393
  type?: 'image' | 'file';
1394
1394
  }
1395
+ /**
1396
+ * 工具调用轨迹步骤(det-oms 风格):流式 tool 事件与历史 tool 行展开后的单步。
1397
+ * status 与 ThoughtChain 链项一致(loading 转圈/success 勾/error 叉)。
1398
+ */
1399
+ interface ToolStepItem {
1400
+ /** 步骤唯一标识(流式 `${toolName}-${序号}`;历史回放由消费方生成) */
1401
+ key: string;
1402
+ /** 展示名(流式经 toolStepLabel 转换后的工具名) */
1403
+ title?: string;
1404
+ /** 步骤状态;缺省视为 loading */
1405
+ status?: 'pending' | 'loading' | 'success' | 'error';
1406
+ /** 补充描述(历史回放的用时/返回量等次要信息) */
1407
+ description?: string;
1408
+ }
1395
1409
  /** 树形消息节点(同构 open-webui 会话消息:parentId/childrenIds 构成分支树) */
1396
1410
  interface MessageNode {
1397
1411
  id: string;
@@ -1399,6 +1413,8 @@ interface MessageNode {
1399
1413
  content: string;
1400
1414
  /** 思考链全文(流式期间由包装层追加) */
1401
1415
  reasoning?: string;
1416
+ /** 工具调用轨迹(det-oms 流式 tool 事件累积/历史 tool 行展开;AiMessage 以 ThoughtChain 渲染) */
1417
+ toolSteps?: ToolStepItem[];
1402
1418
  /** 附件列表 */
1403
1419
  files?: ChatFile[];
1404
1420
  /** 多模型对话中的模型序号(open-webui 语义) */
@@ -1470,6 +1486,10 @@ type __VLS_Props$3 = {
1470
1486
  suggestionsTitle?: string;
1471
1487
  /** 用户上滚免打扰阈值(px):距底不超过该值才自动吸底 */
1472
1488
  scrollThreshold?: number;
1489
+ /** 显示滚到底部悬浮按钮 */
1490
+ showScrollButton?: boolean;
1491
+ /** 距底超过该像素(px)才显示滚到底部悬浮按钮 */
1492
+ scrollButtonThreshold?: number;
1473
1493
  /** 显示消息操作按钮 */
1474
1494
  showActions?: boolean;
1475
1495
  /** 显示分支切换器 */
@@ -1509,6 +1529,11 @@ declare var __VLS_38: {
1509
1529
  declare var __VLS_41: {
1510
1530
  message: MessageNode;
1511
1531
  };
1532
+ declare var __VLS_49: {
1533
+ scrollToBottom: typeof scrollToBottom;
1534
+ awayFromBottom: boolean;
1535
+ };
1536
+ declare var __VLS_65: {};
1512
1537
  type __VLS_Slots$2 = {} & {
1513
1538
  empty?: (props: typeof __VLS_1$1) => any;
1514
1539
  } & {
@@ -1523,6 +1548,10 @@ type __VLS_Slots$2 = {} & {
1523
1548
  'user-name'?: (props: typeof __VLS_38) => any;
1524
1549
  } & {
1525
1550
  'assistant-name'?: (props: typeof __VLS_41) => any;
1551
+ } & {
1552
+ 'scroll-button'?: (props: typeof __VLS_49) => any;
1553
+ } & {
1554
+ 'scroll-button-icon'?: (props: typeof __VLS_65) => any;
1526
1555
  };
1527
1556
  declare const __VLS_base$2: vue.DefineComponent<__VLS_Props$3, {
1528
1557
  scrollToBottom: typeof scrollToBottom;
@@ -1555,6 +1584,8 @@ declare const __VLS_base$2: vue.DefineComponent<__VLS_Props$3, {
1555
1584
  suggestions: AiMessagesSuggestion[];
1556
1585
  suggestionsTitle: string;
1557
1586
  scrollThreshold: number;
1587
+ showScrollButton: boolean;
1588
+ scrollButtonThreshold: number;
1558
1589
  }, {}, {}, {}, string, vue.ComponentProvideOptions, false, {}, any>;
1559
1590
  declare const __VLS_export$3: __VLS_WithSlots$2<typeof __VLS_base$2, __VLS_Slots$2>;
1560
1591
  declare const _default$3: typeof __VLS_export$3;
@@ -1595,6 +1626,10 @@ type __VLS_Props$2 = {
1595
1626
  showHeader?: boolean;
1596
1627
  /** 空态居中:未开始对话时欢迎内容与输入区整体垂直居中,首条消息后恢复输入区固定底部 */
1597
1628
  centerWelcome?: boolean;
1629
+ /** 显示滚到底部悬浮按钮(透传 AiMessages;距底超过 scrollButtonThreshold 时出现) */
1630
+ showScrollButton?: boolean;
1631
+ /** 滚到底部悬浮按钮显示阈值(px,透传 AiMessages) */
1632
+ scrollButtonThreshold?: number;
1598
1633
  /** 显示用户头像(false 时用户消息不渲染头像;助手头像不受影响) */
1599
1634
  showUserAvatar?: boolean;
1600
1635
  /** 显示用户名称(false 时用户消息不渲染头部名称行;助手名称不受影响) */
@@ -1613,6 +1648,8 @@ type __VLS_Props$2 = {
1613
1648
  assistantName?: string;
1614
1649
  /** 输入框占位 */
1615
1650
  placeholder?: string;
1651
+ /** 工具名 → 步骤展示名(透传 useChat toolStepLabel,流式工具轨迹步骤的 title) */
1652
+ toolStepLabel?: (toolName: string) => string;
1616
1653
  /** 输入区阴影效果(透传 Sender;关闭传 false) */
1617
1654
  senderShadow?: boolean;
1618
1655
  /** 空态建议列表 */
@@ -1656,7 +1693,12 @@ declare var __VLS_39: {
1656
1693
  message: MessageNode;
1657
1694
  };
1658
1695
  declare var __VLS_42: {};
1659
- declare var __VLS_78: {};
1696
+ declare var __VLS_45: {
1697
+ scrollToBottom: (smooth?: boolean) => void;
1698
+ awayFromBottom: boolean;
1699
+ };
1700
+ declare var __VLS_48: {};
1701
+ declare var __VLS_84: {};
1660
1702
  type __VLS_Slots$1 = {} & {
1661
1703
  'message-avatar'?: (props: typeof __VLS_24) => any;
1662
1704
  } & {
@@ -1672,7 +1714,11 @@ type __VLS_Slots$1 = {} & {
1672
1714
  } & {
1673
1715
  empty?: (props: typeof __VLS_42) => any;
1674
1716
  } & {
1675
- 'sender-prefix'?: (props: typeof __VLS_78) => any;
1717
+ 'scroll-button'?: (props: typeof __VLS_45) => any;
1718
+ } & {
1719
+ 'scroll-button-icon'?: (props: typeof __VLS_48) => any;
1720
+ } & {
1721
+ 'sender-prefix'?: (props: typeof __VLS_84) => any;
1676
1722
  };
1677
1723
  declare const __VLS_base$1: vue.DefineComponent<__VLS_Props$2, {
1678
1724
  sendMessage: typeof sendMessage;
@@ -1721,10 +1767,13 @@ declare const __VLS_base$1: vue.DefineComponent<__VLS_Props$2, {
1721
1767
  userName: string;
1722
1768
  assistantName: string;
1723
1769
  suggestions: AiChatSuggestion[];
1770
+ showScrollButton: boolean;
1771
+ scrollButtonThreshold: number;
1724
1772
  models: string[];
1725
1773
  adapter: ChatAdapter;
1726
1774
  showHeader: boolean;
1727
1775
  centerWelcome: boolean;
1776
+ toolStepLabel: (toolName: string) => string;
1728
1777
  senderShadow: boolean;
1729
1778
  features: AiChatFeatures;
1730
1779
  allowAttachments: boolean;
@@ -1790,7 +1839,7 @@ declare var __VLS_33: {
1790
1839
  message: MessageNode;
1791
1840
  files: ChatFile[];
1792
1841
  };
1793
- declare var __VLS_52: {
1842
+ declare var __VLS_57: {
1794
1843
  message: MessageNode;
1795
1844
  };
1796
1845
  type __VLS_Slots = {} & {
@@ -1806,7 +1855,7 @@ type __VLS_Slots = {} & {
1806
1855
  } & {
1807
1856
  'message-files'?: (props: typeof __VLS_33) => any;
1808
1857
  } & {
1809
- 'message-actions'?: (props: typeof __VLS_52) => any;
1858
+ 'message-actions'?: (props: typeof __VLS_57) => any;
1810
1859
  };
1811
1860
  declare const __VLS_base: vue.DefineComponent<__VLS_Props$1, {
1812
1861
  message: vue.ComputedRef<MessageNode>;
@@ -1995,6 +2044,8 @@ interface UseChatOptions {
1995
2044
  toolName: string;
1996
2045
  status: 'start' | 'done';
1997
2046
  }) => void;
2047
+ /** 工具名 → 步骤展示名(流式 toolSteps 的 title;缺省原样使用 toolName) */
2048
+ toolStepLabel?: (toolName: string) => string;
1998
2049
  }
1999
2050
  /** 待发送队列项 */
2000
2051
  interface QueueItem {
@@ -2044,4 +2095,4 @@ declare function createMessageTree(initial?: {
2044
2095
  declare const version = "0.1.0";
2045
2096
 
2046
2097
  export { DetOmsChatAdapter, DetOmsError, _default as FvAiArtifacts, _default$2 as FvAiChat, _default$1 as FvAiMessage, _default$3 as FvAiMessages, _default$5 as FvAttachments, _default$f as FvBubble, _default$e as FvBubbleList, _default$4 as FvConversations, _default$b as FvEditorSender, _default$6 as FvFilesCard, _default$h as FvMarkdown, _default$c as FvMentionSender, _default$7 as FvPrompts, _default$d as FvSender, _default$a as FvThinking, _default$9 as FvThoughtChain, _default$g as FvTypewriter, _default$8 as FvWelcome, OpenAIAdapter, XRequest, createLocalStorageAdapter, createMemoryAdapter, createMessageTree, createSSEParser, useChat, useMessages, useRecord, useSend, useXStream, version };
2047
- export type { AdapterChatMessage, AiArtifactItem, AiChatFeatures, AiChatSuggestion, AiMessageBranchInfo, AiMessagesSuggestion, BranchDirection, ChatAdapter, ChatAdapterHandlers, ChatAdapterRequest, ChatFile, DetOmsChatAdapterConfig, DetOmsMessage, DetOmsMessagePage, DetOmsSendBody, DetOmsSessionDetail, DetOmsSessionItem, DetOmsToolEvent, MessageNode, MessageNodeInput, MessageRole, MessageStatus, MessageTree, MessageUsage, OpenAIAdapterConfig, QueueItem, RawUsage, SSEEvent, SSEParser, SendOptions, StorageAdapter, ToolCallItem, UseChatOptions, UseChatReturn, UseMessagesReturn, UseRecordReturn, UseSendReturn, UseXStreamReturn };
2098
+ export type { AdapterChatMessage, AiArtifactItem, AiChatFeatures, AiChatSuggestion, AiMessageBranchInfo, AiMessagesSuggestion, BranchDirection, ChatAdapter, ChatAdapterHandlers, ChatAdapterRequest, ChatFile, DetOmsChatAdapterConfig, DetOmsMessage, DetOmsMessagePage, DetOmsSendBody, DetOmsSessionDetail, DetOmsSessionItem, DetOmsToolEvent, MessageNode, MessageNodeInput, MessageRole, MessageStatus, MessageTree, MessageUsage, OpenAIAdapterConfig, QueueItem, RawUsage, SSEEvent, SSEParser, SendOptions, StorageAdapter, ToolCallItem, ToolStepItem, UseChatOptions, UseChatReturn, UseMessagesReturn, UseRecordReturn, UseSendReturn, UseXStreamReturn };
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .fv-xmarkdown{color:var(--el-text-color-primary,#303133);line-height:1.7;word-break:break-word}.fv-xmarkdown h1,.fv-xmarkdown h2,.fv-xmarkdown h3,.fv-xmarkdown h4,.fv-xmarkdown h5,.fv-xmarkdown h6{color:var(--el-text-color-primary,#303133);font-weight:600;margin:1em 0 .5em}.fv-xmarkdown h1{font-size:1.5em}.fv-xmarkdown h2{font-size:1.3em}.fv-xmarkdown h3{font-size:1.15em}.fv-xmarkdown p{margin:.5em 0}.fv-xmarkdown a{color:var(--el-color-primary,#409eff);text-decoration:none}.fv-xmarkdown a:hover{text-decoration:underline}.fv-xmarkdown blockquote{border-left:4px solid var(--el-border-color,#dcdfe6);color:var(--el-text-color-regular,#606266);margin:.5em 0;padding:.4em 1em}.fv-xmarkdown blockquote,.fv-xmarkdown code{background:var(--el-fill-color-light,#f5f7fa)}.fv-xmarkdown code{border-radius:3px;color:var(--el-color-danger,#f56c6c);font-family:JetBrains Mono,Consolas,Courier New,monospace;font-size:.9em;padding:.15em .4em}.fv-xmarkdown pre{background:#282c34;border-radius:6px;margin:.5em 0;overflow-x:auto;padding:1em}.fv-xmarkdown pre code{background:transparent;color:#dcdfe6;font-size:.9em;line-height:1.6;padding:0}.fv-xmarkdown table{border-collapse:collapse;margin:.5em 0;width:100%}.fv-xmarkdown table td,.fv-xmarkdown table th{border:1px solid var(--el-border-color-lighter,#ebeef5);padding:.5em .8em;text-align:left}.fv-xmarkdown table th{background:var(--el-fill-color-light,#f5f7fa);font-weight:600}.fv-xmarkdown table tr:nth-child(2n) td{background:var(--el-fill-color-blank,#fafcff)}.fv-xmarkdown .katex-display{margin:.5em 0;overflow-x:auto}.fv-typewriter{display:inline-block;max-width:100%;position:relative}.fv-typewriter .fv-typewriter-text{white-space:pre-wrap;word-break:break-word}.fv-typewriter .fv-typewriter-suffix{animation:fv-typewriter-blink 1s step-start infinite;display:inline-block}.fv-typewriter .fv-typewriter-fog{animation:fv-typewriter-fog-in .3s ease-out both;background:linear-gradient(90deg,transparent,var(--fv-typewriter-fog-color,var(--el-bg-color,#fff)));bottom:0;pointer-events:none;position:absolute;right:0;top:0}@keyframes fv-typewriter-blink{0%,to{opacity:1}50%{opacity:0}}@keyframes fv-typewriter-fog-in{0%{opacity:0}to{opacity:1}}.fv-bubble{align-items:flex-start;display:flex;gap:var(--fv-bubble-avatar-gap,12px)}.fv-bubble.is-end{flex-direction:row-reverse;justify-content:flex-end}.fv-bubble.is-end .fv-bubble-main{align-items:flex-end}.fv-bubble .fv-bubble-avatar{display:flex;flex-shrink:0}.fv-bubble .fv-bubble-avatar .el-avatar{height:var(--fv-bubble-avatar-size,36px);width:var(--fv-bubble-avatar-size,36px)}.fv-bubble .fv-bubble-main{align-items:flex-start;display:flex;flex:1;flex-direction:column;max-width:100%;min-width:0}.fv-bubble .fv-bubble-main .fv-bubble-footer,.fv-bubble .fv-bubble-main .fv-bubble-header{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px)}.fv-bubble .fv-bubble-main .fv-bubble-footer{margin-top:4px}.fv-bubble .fv-bubble-content{border-radius:calc(var(--el-border-radius-base, 4px) + 4px);box-sizing:border-box;color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);max-width:100%;min-width:0;padding:var(--el-main-padding,12px) calc(var(--el-main-padding, 12px) + 4px);position:relative;word-break:break-word}.fv-bubble .fv-bubble-content.no-padding{padding:0}.fv-bubble .fv-bubble-content .fv-bubble-text{white-space:pre-wrap}.fv-bubble.shape-round .fv-bubble-content{border-radius:var(--el-border-radius-round,20px)}.fv-bubble.shape-corner .fv-bubble-content{border-start-start-radius:calc(var(--el-border-radius-base, 4px) - 2px)}.fv-bubble.is-end.shape-corner .fv-bubble-content{border-start-end-radius:calc(var(--el-border-radius-base, 4px) - 2px);border-start-start-radius:calc(var(--el-border-radius-base, 4px) + 4px)}.fv-bubble.variant-borderless .fv-bubble-content,.fv-bubble.variant-filled .fv-bubble-content{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-bubble.variant-borderless .fv-bubble-content,.fv-bubble.variant-outlined .fv-bubble-content{border:var(--el-border-width,1px) solid var(--el-border-color,#dcdfe6)}.fv-bubble.variant-outlined .fv-bubble-content{background:none}.fv-bubble.variant-shadow .fv-bubble-content{background:none;box-shadow:var(--el-box-shadow-light,0 0 12px rgba(0,0,0,.12))}.fv-bubble .fv-bubble-content.no-style{background:transparent;border:none;box-shadow:none;padding:0}.fv-bubble .fv-bubble-loading{align-items:center;display:flex;gap:5px;min-height:1em;width:fit-content}.fv-bubble .fv-bubble-loading .fv-bubble-loading-dot{animation:fv-bubble-wave 1s ease-in-out infinite;background-color:var(--el-color-primary,#409eff);border-radius:50%;height:5px;width:5px}@keyframes fv-bubble-wave{0%,to{transform:translateY(-2px)}50%{transform:translateY(2px)}}.fv-bubble-list{display:flex;flex-direction:column;min-height:0;position:relative}.fv-bubble-list .fv-bubble-list-scroll{display:flex;flex-direction:column;gap:16px;min-height:0;overflow-y:auto}.fv-bubble-list .fv-bubble-list-scroll>.fv-bubble{flex-shrink:0}.fv-bubble-list .fv-bubble-list-scroll.always-scrollbar{overflow-y:scroll;scrollbar-width:auto}.fv-bubble-list .fv-bubble-list-scroll.always-scrollbar::-webkit-scrollbar{-webkit-appearance:none;width:6px}.fv-bubble-list .fv-bubble-list-scroll.always-scrollbar::-webkit-scrollbar-thumb{background-color:var(--el-border-color,#dcdfe6);border-radius:3px}.fv-bubble-list .fv-bubble-list-back{align-items:center;bottom:16px;box-shadow:var(--el-box-shadow-light,0 0 12px rgba(0,0,0,.12));display:inline-flex;justify-content:center;left:50%;position:absolute;transform:translateX(-50%);z-index:1}.fv-bubble-list .fv-bubble-list-back .fv-bubble-list-back-icon{align-items:center;display:inline-flex;justify-content:center;line-height:1}.fv-bubble-list-fade-enter-active,.fv-bubble-list-fade-leave-active{transition:opacity .2s ease,transform .2s ease}.fv-bubble-list-fade-enter-from,.fv-bubble-list-fade-leave-to{opacity:0;transform:translate(-50%,4px)}.fv-sender{box-sizing:border-box;display:flex;flex-direction:column;width:100%}.fv-sender .fv-sender-header{animation:fv-sender-slide-down .3s ease;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);max-height:300px;overflow:hidden;padding:8px 12px}.fv-sender .fv-sender-body{background-color:var(--el-fill-color-blank,#fff);border:var(--el-border-width,1px) solid var(--el-border-color,#dcdfe6);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);display:flex;flex-direction:column;gap:6px;padding:8px 12px;transition:border-color .2s}.fv-sender .fv-sender-body .fv-sender-body-top:empty{display:none}.fv-sender .fv-sender-body .fv-sender-row{align-items:flex-end;display:flex;gap:8px}.fv-sender .fv-sender-body .fv-sender-prefix{align-items:center;align-self:center;display:flex;flex-shrink:0}.fv-sender .fv-sender-body .fv-sender-recording{align-items:center;background-color:var(--el-color-primary-light-9,#ecf5ff);border-radius:calc(var(--el-border-radius-base, 4px) + 2px);display:flex;flex:1;gap:8px;min-width:0;outline:none;padding:4px 8px}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-cancel{flex-shrink:0}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-cancel:hover{color:var(--el-color-danger,#f56c6c)}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-wave{align-items:center;direction:rtl;display:flex;flex:1;gap:2px;height:22px;justify-content:flex-end;min-width:0;overflow:hidden}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-wave .fv-sender-recording-bar{background-color:var(--el-color-primary,#409eff);border-radius:1px;flex-shrink:0;min-height:2px;opacity:.75;width:2px}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-duration{color:var(--el-color-primary,#409eff);flex-shrink:0;font-size:var(--el-font-size-small,12px);font-variant-numeric:tabular-nums;min-width:3em;text-align:center}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-confirm{flex-shrink:0}.fv-sender .fv-sender-body .fv-sender-input{display:flex;flex:1;min-width:0;position:relative}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea{background:transparent;border:none;box-sizing:border-box;color:var(--el-text-color-primary,#303133);flex:1;font:inherit;font-family:inherit;font-size:var(--el-font-size-base,14px);line-height:22px;min-width:0;outline:none;padding:4px 0;resize:none}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea::placeholder{color:var(--el-text-color-placeholder,#a8abb2)}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea:disabled{color:var(--el-text-color-disabled,#a8abb2);cursor:not-allowed}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea[readonly]{cursor:default}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-trigger-anchor{bottom:0;height:0;pointer-events:none;position:absolute;width:0}.fv-sender .fv-sender-body .fv-sender-actions{align-items:center;align-self:flex-end;display:flex;flex-shrink:0;gap:4px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-action-left{align-items:center;display:flex;gap:4px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech{color:var(--el-text-color-regular,#606266);padding:6px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech .el-icon{font-size:18px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech:not(.is-disabled):active,.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech:not(.is-disabled):hover{background-color:transparent;color:var(--el-text-color-primary,#303133)}.fv-sender.variant-updown .fv-sender-row{align-items:stretch;flex-direction:column;gap:6px}.fv-sender.variant-updown .fv-sender-row .fv-sender-input{width:100%}.fv-sender.variant-updown .fv-sender-row .fv-sender-actions{align-self:flex-end;justify-content:flex-end}.fv-sender.variant-updown .fv-sender-row .fv-sender-actions:has(.fv-sender-action-left){align-self:stretch}.fv-sender.variant-updown .fv-sender-row .fv-sender-actions:has(.fv-sender-action-left) .fv-sender-action-left{margin-right:auto}.fv-sender.is-focused .fv-sender-body{border-color:var(--el-color-primary,#409eff)}.fv-sender.is-disabled .fv-sender-body{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-sender.has-shadow .fv-sender-body{box-shadow:0 8px 20px 0 var(--el-box-shadow-color,rgba(0,0,0,.08));transition:border-color .2s,box-shadow .2s}.fv-sender.has-shadow.is-focused .fv-sender-body{box-shadow:0 8px 24px 0 var(--el-box-shadow-color,rgba(0,0,0,.12))}.fv-sender .fv-sender-stop{--fv-sender-stop-icon-size:16px;--fv-sender-stop-ring-width:2px;--fv-sender-stop-ring-duration:1.1s;position:relative}.fv-sender .fv-sender-stop .el-icon{align-items:center;display:inline-flex;font-size:var(--fv-sender-stop-icon-size);justify-content:center}.fv-sender .fv-sender-stop .fv-stop-icon{display:block}.fv-sender .fv-sender-stop .fv-sender-stop-ring{height:100%;inset:0;overflow:visible;pointer-events:none;position:absolute;width:100%}.fv-sender .fv-sender-stop .fv-sender-stop-ring .fv-sender-stop-ring-rect{x:calc(var(--fv-sender-stop-ring-width)/2);y:calc(var(--fv-sender-stop-ring-width)/2);fill:none;stroke:rgb(255,255,255,var(--ring-alpha,.9));stroke-width:var(--fv-sender-stop-ring-width);stroke-dasharray:0 calc(100 - var(--ring-len, 10)) var(--ring-len,10) 0;animation:fv-sender-stop-spin var(--fv-sender-stop-ring-duration) linear infinite;height:calc(100% - var(--fv-sender-stop-ring-width));width:calc(100% - var(--fv-sender-stop-ring-width))}@media (prefers-reduced-motion:reduce){.fv-sender .fv-sender-stop .fv-sender-stop-ring-rect{animation:none}}.fv-sender .fv-sender-footer{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-base,14px);padding:6px 12px}@keyframes fv-sender-slide-down{0%{max-height:0;opacity:0}to{max-height:300px;opacity:1}}@keyframes fv-sender-stop-spin{to{stroke-dashoffset:-100}}.fv-mention-sender{position:relative}.fv-mention-sender .fv-mention-anchor{bottom:0;height:0;pointer-events:none;position:absolute;width:0}.fv-mention-popover .fv-mention-panel{max-height:260px;overflow-y:auto;padding:4px}.fv-mention-popover .fv-mention-title{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:4px 8px}.fv-mention-popover .fv-mention-loading{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);padding:8px;text-align:center}.fv-mention-popover .fv-mention-item{align-items:center;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-primary,#303133);cursor:pointer;display:flex;font-size:var(--el-font-size-base,14px);gap:8px;padding:6px 8px}.fv-mention-popover .fv-mention-item.is-active,.fv-mention-popover .fv-mention-item:hover{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-mention-popover .fv-mention-item .fv-mention-avatar{align-items:center;background-color:var(--el-fill-color,#e9e9eb);border-radius:50%;color:var(--el-text-color-regular,#606266);display:inline-flex;flex-shrink:0;font-size:var(--el-font-size-small,12px);height:24px;justify-content:center;overflow:hidden;width:24px}.fv-mention-popover .fv-mention-item .fv-mention-avatar img{height:100%;object-fit:cover;width:100%}.fv-mention-popover .fv-mention-item .fv-mention-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-editor-sender{box-sizing:border-box;display:flex;flex-direction:column;width:100%}.fv-editor-sender .fv-editor-header{animation:fv-editor-slide-down .3s ease;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);max-height:300px;overflow:hidden;padding:8px 12px}.fv-editor-sender .fv-editor-body{align-items:flex-end;background-color:var(--el-fill-color-blank,#fff);border:var(--el-border-width,1px) solid var(--el-border-color,#dcdfe6);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);display:flex;gap:8px;padding:8px 12px;transition:border-color .2s}.fv-editor-sender .fv-editor-body .fv-editor-prefix{align-items:center;align-self:center;display:flex;flex-shrink:0}.fv-editor-sender .fv-editor-body .fv-editor-input{display:flex;flex:1;min-width:0;position:relative}.fv-editor-sender .fv-editor-body .fv-editor-input .fv-editor-content{background:transparent;box-sizing:border-box;color:var(--el-text-color-primary,#303133);flex:1;font:inherit;font-family:inherit;font-size:var(--el-font-size-base,14px);line-height:22px;max-height:220px;min-width:0;outline:none;overflow-y:auto;padding:4px 0;white-space:pre-wrap;word-break:break-word}.fv-editor-sender .fv-editor-body .fv-editor-input .fv-editor-content:empty:before{color:var(--el-text-color-placeholder,#a8abb2);content:attr(data-placeholder);pointer-events:none}.fv-editor-sender .fv-editor-body .fv-editor-input .fv-editor-anchor{bottom:0;height:0;pointer-events:none;position:absolute;width:0}.fv-editor-sender .fv-editor-body .fv-editor-actions{align-items:center;align-self:flex-end;display:flex;flex-shrink:0;gap:4px}.fv-editor-sender .fv-editor-tag{align-items:center;background-color:var(--el-color-primary-light-9,#ecf5ff);border-radius:var(--el-border-radius-base,4px);box-sizing:border-box;color:var(--el-color-primary,#409eff);display:inline-flex;font-size:var(--el-font-size-base,14px);line-height:20px;margin:0 1px;max-width:100%;padding:0 6px;user-select:all;white-space:nowrap}.fv-editor-sender .fv-editor-tag.fv-editor-tag-inputTag{padding:0 2px}.fv-editor-sender .fv-editor-tag.fv-editor-tag-inputTag .fv-editor-tag-input{background:transparent;border:none;box-sizing:border-box;color:inherit;font:inherit;line-height:20px;outline:none;padding:0 4px;width:120px}.fv-editor-sender .fv-editor-tag.fv-editor-tag-inputTag .fv-editor-tag-input::placeholder{color:var(--el-text-color-placeholder,#a8abb2)}.fv-editor-sender .fv-editor-tag.fv-editor-tag-htmlTag{display:inline;user-select:text;white-space:normal}.fv-editor-sender.variant-updown .fv-editor-body{align-items:stretch;flex-direction:column;gap:6px}.fv-editor-sender.variant-updown .fv-editor-body .fv-editor-input{width:100%}.fv-editor-sender.variant-updown .fv-editor-body .fv-editor-actions{align-self:flex-end;justify-content:flex-end}.fv-editor-sender.device-h5 .fv-editor-body{padding:6px 10px}.fv-editor-sender.is-focused .fv-editor-body{border-color:var(--el-color-primary,#409eff)}.fv-editor-sender.is-disabled .fv-editor-body{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-editor-sender .fv-editor-footer{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-base,14px);padding:6px 12px}.fv-editor-mention-popover .fv-editor-mention-panel{max-height:260px;overflow-y:auto;padding:4px}.fv-editor-mention-popover .fv-editor-mention-title{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:4px 8px}.fv-editor-mention-popover .fv-editor-mention-loading{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);padding:8px;text-align:center}.fv-editor-mention-popover .fv-editor-mention-item{align-items:center;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-primary,#303133);cursor:pointer;display:flex;font-size:var(--el-font-size-base,14px);gap:8px;padding:6px 8px}.fv-editor-mention-popover .fv-editor-mention-item.is-active,.fv-editor-mention-popover .fv-editor-mention-item:hover{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-editor-mention-popover .fv-editor-mention-item .fv-editor-mention-avatar{align-items:center;background-color:var(--el-fill-color,#e9e9eb);border-radius:50%;color:var(--el-text-color-regular,#606266);display:inline-flex;flex-shrink:0;font-size:var(--el-font-size-small,12px);height:24px;justify-content:center;overflow:hidden;width:24px}.fv-editor-mention-popover .fv-editor-mention-item .fv-editor-mention-avatar img{height:100%;object-fit:cover;width:100%}.fv-editor-mention-popover .fv-editor-mention-item .fv-editor-mention-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-editor-tip-popover .fv-editor-tip-panel{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:6px 8px}.fv-editor-select-dialog .fv-editor-select-group+.fv-editor-select-group{margin-top:12px}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-title{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);font-weight:600;margin-bottom:8px}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-grid{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(96px,1fr))}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item{align-items:center;border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:var(--el-border-radius-base,4px);cursor:pointer;display:flex;flex-direction:column;gap:4px;padding:8px;transition:border-color .2s}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item:hover{border-color:var(--el-color-primary,#409eff)}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item .fv-editor-select-preview{border-radius:var(--el-border-radius-base,4px);height:56px;object-fit:cover;width:100%}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item .fv-editor-select-name{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-small,12px);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@keyframes fv-editor-slide-down{0%{max-height:0;opacity:0}to{max-height:300px;opacity:1}}.fv-thinking{background-color:var(--fv-thinking-bg,transparent);border-radius:var(--el-border-radius-base,4px);box-sizing:border-box;color:var(--fv-thinking-color,var(--el-text-color-regular,#606266));display:flex;flex-direction:column;width:100%}.fv-thinking .fv-thinking-toggle{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:inline-flex;font:inherit;font-size:var(--el-font-size-base,14px);gap:6px;line-height:22px;padding:4px 0;text-align:left;transition:color .2s;user-select:none}.fv-thinking .fv-thinking-toggle:hover{color:var(--fv-thinking-color,var(--el-color-primary,#409eff))}.fv-thinking .fv-thinking-toggle:focus{outline:none}.fv-thinking.is-disabled .fv-thinking-toggle{cursor:not-allowed;opacity:.6}.fv-thinking .fv-thinking-status-icon{align-items:center;display:inline-flex;height:16px;justify-content:center;width:16px}.fv-thinking .fv-thinking-status-icon .fv-thinking-dot{background-color:var(--el-color-primary,#409eff);border-radius:50%;height:8px;width:8px}.fv-thinking .fv-thinking-status-icon .is-loading{animation:fv-thinking-rotate 1s linear infinite;color:var(--el-color-primary,#409eff)}.fv-thinking .fv-thinking-status-icon .is-success{color:var(--el-color-success,#67c23a)}.fv-thinking .fv-thinking-status-icon .is-error{color:var(--el-color-danger,#f56c6c)}.fv-thinking .fv-thinking-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-thinking .fv-thinking-arrow{align-items:center;display:inline-flex;transition:transform .3s ease}.fv-thinking .fv-thinking-arrow.is-open{transform:rotate(180deg)}.fv-thinking .fv-thinking-content{box-sizing:border-box;color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-base,14px);line-height:22px;padding:8px 0 8px 22px;white-space:pre-wrap;word-break:break-word}@keyframes fv-thinking-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fv-chain{box-sizing:border-box;display:flex;font-size:var(--el-font-size-base,14px)}.fv-chain.is-vertical{flex-direction:column}.fv-chain.is-vertical .fv-chain-item{display:flex;gap:10px}.fv-chain.is-vertical .fv-chain-item:not(:last-child) .fv-chain-node:before{background-color:var(--el-border-color-lighter,#ebeef5);bottom:-4px;content:"";left:50%;margin-left:-1px;position:absolute;top:18px;width:2px}.fv-chain.is-horizontal{flex-direction:row;gap:24px}.fv-chain.is-horizontal .fv-chain-item{align-items:flex-start;display:flex;gap:6px}.fv-chain .fv-chain-node{align-items:center;display:inline-flex;flex-shrink:0;font-size:16px;height:18px;justify-content:center;position:relative;width:18px}.fv-chain .fv-chain-node .fv-chain-dot{background-color:var(--el-fill-color-blank,#fff);border:2px solid var(--el-border-color,#dcdfe6);border-radius:50%;box-sizing:border-box;height:8px;width:8px}.fv-chain .fv-chain-item.status-success .fv-chain-node{color:var(--el-color-success,#67c23a)}.fv-chain .fv-chain-item.status-success .fv-chain-node .fv-chain-dot{background-color:var(--el-color-success,#67c23a);border-color:var(--el-color-success,#67c23a)}.fv-chain .fv-chain-item.status-error .fv-chain-node{color:var(--el-color-danger,#f56c6c)}.fv-chain .fv-chain-item.status-error .fv-chain-node .fv-chain-dot{background-color:var(--el-color-danger,#f56c6c);border-color:var(--el-color-danger,#f56c6c)}.fv-chain .fv-chain-item.status-loading .fv-chain-node{color:var(--el-color-primary,#409eff)}.fv-chain .fv-chain-item.status-loading .fv-chain-node .is-loading{animation:fv-chain-rotate 1s linear infinite}.fv-chain .fv-chain-item.status-loading .fv-chain-node .fv-chain-dot{border-color:var(--el-color-primary,#409eff)}.fv-chain .fv-chain-item.status-pending .fv-chain-title{color:var(--el-text-color-placeholder,#a8abb2)}.fv-chain .fv-chain-main{flex:1;min-width:0;padding-bottom:4px}.fv-chain .fv-chain-main .fv-chain-title{color:var(--el-text-color-primary,#303133);line-height:22px}.fv-chain .fv-chain-main .fv-chain-description{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-small,12px);line-height:20px;word-break:break-word}@keyframes fv-chain-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fv-welcome{box-sizing:border-box;flex-direction:column;padding:var(--el-main-padding,20px);text-align:center;width:100%}.fv-welcome,.fv-welcome-icon{align-items:center;display:flex;justify-content:center}.fv-welcome-icon{margin-bottom:16px}.fv-welcome-icon .fv-welcome-avatar{background-color:var(--el-fill-color-light,#f5f7fa);border-radius:calc(var(--el-border-radius-base, 4px) + 8px);color:var(--el-color-primary,#409eff);font-size:36px;height:72px;width:72px}.fv-welcome-name{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-extra-large,20px);font-weight:600;line-height:1.4;margin:0}.fv-welcome-description{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);margin:8px 0 0;max-width:480px;white-space:pre-wrap;word-break:break-word}.fv-prompts{box-sizing:border-box;width:100%}.fv-prompts .fv-prompts-title{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);margin-bottom:12px}.fv-prompts .fv-prompts-list{display:flex;flex-wrap:wrap;gap:12px}.fv-prompts .fv-prompt-item{background-color:var(--el-bg-color,#fff);border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);box-sizing:border-box;cursor:pointer;flex:1 1 200px;max-width:100%;padding:12px 14px;transition:background-color var(--el-transition-duration,.3s),border-color var(--el-transition-duration,.3s)}.fv-prompts .fv-prompt-item:hover:not(.is-disabled){background-color:var(--el-fill-color-light,#f5f7fa);border-color:var(--el-border-color,#dcdfe6)}.fv-prompts .fv-prompt-item:focus-visible:not(.is-disabled){border-color:var(--el-color-primary,#409eff);outline:none}.fv-prompts .fv-prompt-item.is-disabled{background-color:var(--el-fill-color-lighter,#fafafa);cursor:not-allowed;opacity:.6}.fv-prompts .fv-prompt-item.is-disabled,.fv-prompts .fv-prompt-item.is-disabled .fv-prompt-item-description,.fv-prompts .fv-prompt-item.is-disabled .fv-prompt-item-icon,.fv-prompts .fv-prompt-item.is-disabled .fv-prompt-item-label{color:var(--el-text-color-placeholder,#a8abb2)}.fv-prompts .fv-prompt-item .fv-prompt-item-main{align-items:flex-start;display:flex;gap:10px}.fv-prompts .fv-prompt-item .fv-prompt-item-icon{color:var(--el-color-primary,#409eff);flex-shrink:0;font-size:18px;margin-top:2px}.fv-prompts .fv-prompt-item .fv-prompt-item-text{flex:1;min-width:0}.fv-prompts .fv-prompt-item .fv-prompt-item-label{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);font-weight:500;line-height:var(--el-font-line-height-primary,24px);word-break:break-word}.fv-prompts .fv-prompt-item .fv-prompt-item-description{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);line-height:var(--el-font-line-height-primary,24px);margin-top:2px;word-break:break-word}.fv-files-card{align-items:center;background-color:var(--el-bg-color,#fff);border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);box-sizing:border-box;display:flex;gap:8px;max-width:100%;min-width:0;padding:8px 24px 8px 10px;position:relative;transition:border-color var(--el-transition-duration,.3s)}.fv-files-card .fv-files-card-icon{color:var(--el-color-primary,#409eff);flex-shrink:0;font-size:20px}.fv-files-card .fv-files-card-info{flex:1;min-width:0}.fv-files-card .fv-files-card-name{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-small,12px);line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-files-card .fv-files-card-size{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-extra-small,12px);line-height:16px;white-space:nowrap}.fv-files-card .fv-files-card-thumb{align-items:center;background-color:var(--el-fill-color-light,#f5f7fa);border-radius:var(--el-border-radius-base,4px);display:flex;flex-shrink:0;height:48px;justify-content:center;overflow:hidden;width:48px}.fv-files-card .fv-files-card-thumb .fv-files-card-img{display:block;height:100%;object-fit:cover;width:100%}.fv-files-card .fv-files-card-thumb .fv-files-card-thumb-placeholder{color:var(--el-text-color-placeholder,#a8abb2);font-size:20px}.fv-files-card .fv-files-card-status{align-items:center;background-color:var(--el-bg-color,#fff);border-radius:50%;bottom:-8px;display:flex;height:16px;justify-content:center;left:50%;position:absolute;transform:translateX(-50%);width:16px}.fv-files-card .fv-files-card-status .fv-files-card-loading{animation:fv-files-card-rotating 1.5s linear infinite;color:var(--el-color-primary,#409eff);font-size:14px}.fv-files-card .fv-files-card-remove{align-items:center;background-color:transparent;border:none;border-radius:50%;color:var(--el-text-color-secondary,#909399);cursor:pointer;display:flex;font-size:12px;height:18px;justify-content:center;opacity:0;padding:0;position:absolute;right:2px;top:2px;transition:opacity var(--el-transition-duration,.3s),color var(--el-transition-duration,.3s),background-color var(--el-transition-duration,.3s);width:18px}.fv-files-card .fv-files-card-remove:hover{background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-color-danger,#f56c6c)}.fv-files-card:hover .fv-files-card-remove{opacity:1}.fv-files-card.is-error{border-color:var(--el-color-danger,#f56c6c)}.fv-files-card.is-error .fv-files-card-name{color:var(--el-color-danger,#f56c6c)}@keyframes fv-files-card-rotating{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fv-attachments{align-items:flex-start;box-sizing:border-box;display:flex;gap:8px;width:100%}.fv-attachments .fv-attachments-input{display:none}.fv-attachments .fv-attachments-trigger{align-items:center;background-color:transparent;border:none;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-secondary,#909399);cursor:pointer;display:flex;flex-shrink:0;font-size:16px;height:32px;justify-content:center;padding:0;transition:color var(--el-transition-duration,.3s),background-color var(--el-transition-duration,.3s);width:32px}.fv-attachments .fv-attachments-trigger:hover:not(:disabled){background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-color-primary,#409eff)}.fv-attachments .fv-attachments-trigger.is-full,.fv-attachments .fv-attachments-trigger:disabled{color:var(--el-text-color-placeholder,#a8abb2);cursor:not-allowed}.fv-attachments .fv-attachments-list{display:flex;flex-wrap:wrap;gap:8px;min-width:0}.fv-attachments .fv-attachments-item{align-items:center;display:flex;min-width:0;position:relative}.fv-attachments .fv-attachments-item .fv-files-card{max-width:240px}.fv-attachments .fv-attachments-item .fv-attachments-retry{align-items:center;background-color:transparent;border:none;border-radius:50%;color:var(--el-text-color-secondary,#909399);cursor:pointer;display:flex;font-size:14px;height:20px;justify-content:center;margin-left:4px;padding:0;transition:color var(--el-transition-duration,.3s),background-color var(--el-transition-duration,.3s);width:20px}.fv-attachments .fv-attachments-item .fv-attachments-retry:hover{background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-color-primary,#409eff)}.fv-attachments .fv-attachments-tip{color:var(--el-text-color-placeholder,#a8abb2);flex:1;font-size:var(--el-font-size-extra-small,12px);line-height:32px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-conversations{box-sizing:border-box;overflow-y:auto;width:100%}.fv-conversations .fv-conversations-group .fv-conversations-group-title{background-color:var(--el-bg-color,#fff);color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-extra-small,12px);line-height:20px;padding:8px 12px 4px;position:sticky;top:0;z-index:1}.fv-conversations .fv-conversations-item{align-items:center;border-radius:var(--el-border-radius-base,4px);cursor:pointer;display:flex;gap:4px;padding:0 8px 0 12px;transition:background-color .2s;user-select:none}.fv-conversations .fv-conversations-item:hover{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-conversations .fv-conversations-item:hover .fv-conversations-menu-btn{opacity:1;pointer-events:auto}.fv-conversations .fv-conversations-item.is-active{background-color:var(--el-color-primary-light-9,#ecf5ff);color:var(--el-color-primary,#409eff)}.fv-conversations .fv-conversations-item.is-active .fv-conversations-item-label{color:var(--el-color-primary,#409eff);font-weight:600}.fv-conversations .fv-conversations-item.is-disabled{color:var(--el-text-color-disabled,#a8abb2);cursor:not-allowed}.fv-conversations .fv-conversations-item.is-disabled .fv-conversations-item-label{color:var(--el-text-color-disabled,#a8abb2)}.fv-conversations .fv-conversations-item.is-disabled:hover{background-color:transparent}.fv-conversations .fv-conversations-item .fv-conversations-item-content{flex:1;min-width:0;padding:9px 0}.fv-conversations .fv-conversations-item .fv-conversations-item-content .fv-conversations-item-label{color:var(--el-text-color-regular,#606266);display:block;font-size:var(--el-font-size-base,14px);line-height:22px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-conversations .fv-conversations-item .fv-conversations-menu-btn{align-items:center;background:transparent;border:none;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-secondary,#909399);cursor:pointer;display:inline-flex;flex-shrink:0;height:24px;justify-content:center;opacity:0;padding:0;pointer-events:none;transition:opacity .2s;width:24px}.fv-conversations .fv-conversations-item .fv-conversations-menu-btn:hover{background-color:var(--el-fill-color,#f0f2f5);color:var(--el-text-color-primary,#303133)}.fv-conversations.show-menu-always .fv-conversations-item .fv-conversations-menu-btn{opacity:1;pointer-events:auto}.fv-msg{align-items:flex-start;box-sizing:border-box;display:flex;gap:12px;padding:8px 0;width:100%}.fv-msg .fv-msg-avatar{background-color:var(--el-fill-color-light,#f5f7fa);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);color:var(--el-text-color-secondary,#909399);flex-shrink:0;font-size:18px;height:32px;width:32px}.fv-msg .fv-msg-avatar,.fv-msg .fv-msg-avatar-bot{align-items:center;display:flex;justify-content:center}.fv-msg .fv-msg-avatar-bot{background-color:var(--el-color-primary,#409eff);border-radius:inherit;color:#fff;height:100%;width:100%}.fv-msg .fv-msg-avatar-img{border-radius:inherit;display:block;height:100%;object-fit:cover;width:100%}.fv-msg.is-user .fv-msg-avatar{background-color:var(--el-color-primary-light-8,#d9ecff);color:var(--el-color-primary,#409eff);order:2}.fv-msg .fv-msg-main{align-items:flex-start;display:flex;flex:1;flex-direction:column;min-width:0}.fv-msg .fv-msg-main .fv-msg-header{align-items:center;color:var(--el-text-color-secondary,#909399);display:flex;font-size:var(--el-font-size-small,12px);gap:8px;margin-bottom:2px}.fv-msg .fv-msg-main .fv-msg-header .fv-msg-model{background-color:var(--el-fill-color,#f0f2f5);border-radius:var(--el-border-radius-base,4px);line-height:18px;padding:0 6px}.fv-msg .fv-msg-main .fv-msg-files{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:4px}.fv-msg .fv-msg-main .fv-msg-files .fv-msg-file{align-items:center;border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-regular,#606266);display:inline-flex;font-size:var(--el-font-size-small,12px);padding:4px 8px}.fv-msg .fv-msg-main .fv-msg-files .fv-msg-file .fv-msg-file-img{border-radius:var(--el-border-radius-base,4px);max-height:64px;max-width:64px;object-fit:cover}.fv-msg .fv-msg-main .fv-msg-content{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);max-width:100%;min-width:0;word-break:break-word}.fv-msg .fv-msg-main .fv-msg-content .fv-msg-error{color:var(--el-color-danger,#f56c6c)}.fv-msg .fv-msg-main .fv-msg-content .fv-msg-pending{align-items:center;display:inline-flex;gap:4px;padding:4px 0}.fv-msg .fv-msg-main .fv-msg-content .fv-msg-pending .fv-msg-dot{animation:fv-msg-blink 1s infinite;background-color:var(--el-text-color-secondary,#909399);border-radius:50%;height:6px;width:6px}.fv-msg .fv-msg-main .fv-msg-content-user{background-color:var(--el-fill-color-light,#f5f7fa);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);padding:8px 12px;white-space:pre-wrap}.fv-msg.is-user{flex-direction:row;justify-content:flex-end}.fv-msg.is-user .fv-msg-main{align-items:flex-end}.fv-msg .fv-msg-actions{align-items:center;display:flex;gap:2px;margin-top:2px}.fv-msg .fv-msg-actions .el-button+.el-button{margin-left:0}.fv-msg .fv-msg-actions .fv-msg-branch{align-items:center;display:inline-flex;gap:2px;margin-left:6px}.fv-msg .fv-msg-actions .fv-msg-branch .fv-msg-branch-label{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:0 2px}.fv-msg.is-user .fv-msg-actions{opacity:0;pointer-events:none;transition:opacity .15s}.fv-msg.is-user .fv-msg-actions .fv-msg-branch{margin-left:0}.fv-msg.is-user:focus-within .fv-msg-actions,.fv-msg.is-user:hover .fv-msg-actions{opacity:1;pointer-events:auto}@keyframes fv-msg-blink{0%,to{opacity:.3}50%{opacity:1}}.fv-messages{box-sizing:border-box;display:flex;flex:1;flex-direction:column;min-height:0;width:100%}.fv-messages .fv-messages-scroll{box-sizing:border-box;flex:1;min-height:0;overflow-y:auto;padding:0 16px}.fv-messages .fv-messages-inner{margin:0 auto;max-width:var(--fv-messages-max-width,none)}.fv-messages .fv-messages-empty{align-items:center;box-sizing:border-box;display:flex;flex:1;flex-direction:column;justify-content:center;padding:32px 16px}.fv-messages .fv-messages-empty .fv-messages-prompts{margin-top:8px;max-width:640px;width:100%}.fv-ai-chat{background-color:var(--el-bg-color,#fff);box-sizing:border-box;color:var(--el-text-color-primary,#303133);display:flex;flex-direction:column;height:100%;min-height:0;width:100%}.fv-ai-chat .fv-ai-chat-header{align-items:center;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);display:flex;flex-shrink:0;gap:12px;justify-content:space-between;padding:8px 16px}.fv-ai-chat .fv-ai-chat-header .fv-ai-chat-title{font-size:var(--el-font-size-base,14px);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-ai-chat .fv-ai-chat-header .fv-ai-chat-models{flex-shrink:0;width:220px}.fv-ai-chat .fv-ai-chat-body{display:flex;flex:1;min-height:0;overflow:hidden}.fv-ai-chat .fv-ai-chat-footer{flex-shrink:0;padding:8px 16px 12px}.fv-ai-chat.is-center-welcome .fv-ai-chat-body{flex:0 1 auto;margin-top:auto;min-height:0}.fv-ai-chat.is-center-welcome .fv-ai-chat-footer{margin-bottom:auto}html.dark .fv-ai-chat{background-color:var(--el-bg-color,#141414)}.fv-artifacts{background-color:var(--el-bg-color,#fff);border-left:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);box-sizing:border-box;display:flex;flex-direction:column;flex-shrink:0;max-width:60%;overflow:hidden;width:420px}.fv-artifacts .fv-artifacts-tabs{align-items:center;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);display:flex;flex-shrink:0;gap:4px;overflow-x:auto;padding:6px 8px}.fv-artifacts .fv-artifacts-tabs .fv-artifact-tab{background:transparent;border:none;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-regular,#606266);cursor:pointer;flex-shrink:0;font-size:var(--el-font-size-small,12px);line-height:1.4;padding:4px 10px;white-space:nowrap}.fv-artifacts .fv-artifacts-tabs .fv-artifact-tab:hover{background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-text-color-primary,#303133)}.fv-artifacts .fv-artifacts-tabs .fv-artifact-tab.is-active{background-color:var(--el-color-primary-light-9,#ecf5ff);color:var(--el-color-primary,#409eff)}.fv-artifacts .fv-artifacts-tabs .fv-artifacts-spacer{flex:1}.fv-artifacts .fv-artifacts-frame{background-color:var(--el-bg-color-page,#f2f3f5);border:none;flex:1;min-height:0;width:100%}html.dark .fv-artifacts{background-color:var(--el-bg-color,#141414)}
1
+ .fv-xmarkdown{color:var(--el-text-color-primary,#303133);line-height:1.7;word-break:break-word}.fv-xmarkdown h1,.fv-xmarkdown h2,.fv-xmarkdown h3,.fv-xmarkdown h4,.fv-xmarkdown h5,.fv-xmarkdown h6{color:var(--el-text-color-primary,#303133);font-weight:600;margin:1em 0 .5em}.fv-xmarkdown h1{font-size:1.5em}.fv-xmarkdown h2{font-size:1.3em}.fv-xmarkdown h3{font-size:1.15em}.fv-xmarkdown p{margin:.5em 0}.fv-xmarkdown a{color:var(--el-color-primary,#409eff);text-decoration:none}.fv-xmarkdown a:hover{text-decoration:underline}.fv-xmarkdown blockquote{border-left:4px solid var(--el-border-color,#dcdfe6);color:var(--el-text-color-regular,#606266);margin:.5em 0;padding:.4em 1em}.fv-xmarkdown blockquote,.fv-xmarkdown code{background:var(--el-fill-color-light,#f5f7fa)}.fv-xmarkdown code{border-radius:3px;color:var(--el-color-danger,#f56c6c);font-family:JetBrains Mono,Consolas,Courier New,monospace;font-size:.9em;padding:.15em .4em}.fv-xmarkdown pre{background:#282c34;border-radius:6px;margin:.5em 0;overflow-x:auto;padding:1em}.fv-xmarkdown pre code{background:transparent;color:#dcdfe6;font-size:.9em;line-height:1.6;padding:0}.fv-xmarkdown table{border-collapse:collapse;margin:.5em 0;width:100%}.fv-xmarkdown table td,.fv-xmarkdown table th{border:1px solid var(--el-border-color-lighter,#ebeef5);padding:.5em .8em;text-align:left}.fv-xmarkdown table th{background:var(--el-fill-color-light,#f5f7fa);font-weight:600}.fv-xmarkdown table tr:nth-child(2n) td{background:var(--el-fill-color-blank,#fafcff)}.fv-xmarkdown .katex-display{margin:.5em 0;overflow-x:auto}.fv-typewriter{display:inline-block;max-width:100%;position:relative}.fv-typewriter .fv-typewriter-text{white-space:pre-wrap;word-break:break-word}.fv-typewriter .fv-typewriter-suffix{animation:fv-typewriter-blink 1s step-start infinite;display:inline-block}.fv-typewriter .fv-typewriter-fog{animation:fv-typewriter-fog-in .3s ease-out both;background:linear-gradient(90deg,transparent,var(--fv-typewriter-fog-color,var(--el-bg-color,#fff)));bottom:0;pointer-events:none;position:absolute;right:0;top:0}@keyframes fv-typewriter-blink{0%,to{opacity:1}50%{opacity:0}}@keyframes fv-typewriter-fog-in{0%{opacity:0}to{opacity:1}}.fv-bubble{align-items:flex-start;display:flex;gap:var(--fv-bubble-avatar-gap,12px)}.fv-bubble.is-end{flex-direction:row-reverse;justify-content:flex-end}.fv-bubble.is-end .fv-bubble-main{align-items:flex-end}.fv-bubble .fv-bubble-avatar{display:flex;flex-shrink:0}.fv-bubble .fv-bubble-avatar .el-avatar{height:var(--fv-bubble-avatar-size,36px);width:var(--fv-bubble-avatar-size,36px)}.fv-bubble .fv-bubble-main{align-items:flex-start;display:flex;flex:1;flex-direction:column;max-width:100%;min-width:0}.fv-bubble .fv-bubble-main .fv-bubble-footer,.fv-bubble .fv-bubble-main .fv-bubble-header{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px)}.fv-bubble .fv-bubble-main .fv-bubble-footer{margin-top:4px}.fv-bubble .fv-bubble-content{border-radius:calc(var(--el-border-radius-base, 4px) + 4px);box-sizing:border-box;color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);max-width:100%;min-width:0;padding:var(--el-main-padding,12px) calc(var(--el-main-padding, 12px) + 4px);position:relative;word-break:break-word}.fv-bubble .fv-bubble-content.no-padding{padding:0}.fv-bubble .fv-bubble-content .fv-bubble-text{white-space:pre-wrap}.fv-bubble.shape-round .fv-bubble-content{border-radius:var(--el-border-radius-round,20px)}.fv-bubble.shape-corner .fv-bubble-content{border-start-start-radius:calc(var(--el-border-radius-base, 4px) - 2px)}.fv-bubble.is-end.shape-corner .fv-bubble-content{border-start-end-radius:calc(var(--el-border-radius-base, 4px) - 2px);border-start-start-radius:calc(var(--el-border-radius-base, 4px) + 4px)}.fv-bubble.variant-borderless .fv-bubble-content,.fv-bubble.variant-filled .fv-bubble-content{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-bubble.variant-borderless .fv-bubble-content,.fv-bubble.variant-outlined .fv-bubble-content{border:var(--el-border-width,1px) solid var(--el-border-color,#dcdfe6)}.fv-bubble.variant-outlined .fv-bubble-content{background:none}.fv-bubble.variant-shadow .fv-bubble-content{background:none;box-shadow:var(--el-box-shadow-light,0 0 12px rgba(0,0,0,.12))}.fv-bubble .fv-bubble-content.no-style{background:transparent;border:none;box-shadow:none;padding:0}.fv-bubble .fv-bubble-loading{align-items:center;display:flex;gap:5px;min-height:1em;width:fit-content}.fv-bubble .fv-bubble-loading .fv-bubble-loading-dot{animation:fv-bubble-wave 1s ease-in-out infinite;background-color:var(--el-color-primary,#409eff);border-radius:50%;height:5px;width:5px}@keyframes fv-bubble-wave{0%,to{transform:translateY(-2px)}50%{transform:translateY(2px)}}.fv-bubble-list{display:flex;flex-direction:column;min-height:0;position:relative}.fv-bubble-list .fv-bubble-list-scroll{display:flex;flex-direction:column;gap:16px;min-height:0;overflow-y:auto}.fv-bubble-list .fv-bubble-list-scroll>.fv-bubble{flex-shrink:0}.fv-bubble-list .fv-bubble-list-scroll.always-scrollbar{overflow-y:scroll;scrollbar-width:auto}.fv-bubble-list .fv-bubble-list-scroll.always-scrollbar::-webkit-scrollbar{-webkit-appearance:none;width:6px}.fv-bubble-list .fv-bubble-list-scroll.always-scrollbar::-webkit-scrollbar-thumb{background-color:var(--el-border-color,#dcdfe6);border-radius:3px}.fv-bubble-list .fv-bubble-list-back{align-items:center;bottom:16px;box-shadow:var(--el-box-shadow-light,0 0 12px rgba(0,0,0,.12));display:inline-flex;justify-content:center;left:50%;position:absolute;transform:translateX(-50%);z-index:1}.fv-bubble-list .fv-bubble-list-back .fv-bubble-list-back-icon{align-items:center;display:inline-flex;justify-content:center;line-height:1}.fv-bubble-list-fade-enter-active,.fv-bubble-list-fade-leave-active{transition:opacity .2s ease,transform .2s ease}.fv-bubble-list-fade-enter-from,.fv-bubble-list-fade-leave-to{opacity:0;transform:translate(-50%,4px)}.fv-sender{box-sizing:border-box;display:flex;flex-direction:column;width:100%}.fv-sender .fv-sender-header{animation:fv-sender-slide-down .3s ease;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);max-height:300px;overflow:hidden;padding:8px 12px}.fv-sender .fv-sender-body{background-color:var(--el-fill-color-blank,#fff);border:var(--el-border-width,1px) solid var(--el-border-color,#dcdfe6);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);display:flex;flex-direction:column;gap:6px;padding:8px 12px;transition:border-color .2s}.fv-sender .fv-sender-body .fv-sender-body-top:empty{display:none}.fv-sender .fv-sender-body .fv-sender-row{align-items:flex-end;display:flex;gap:8px}.fv-sender .fv-sender-body .fv-sender-prefix{align-items:center;align-self:center;display:flex;flex-shrink:0}.fv-sender .fv-sender-body .fv-sender-recording{align-items:center;background-color:var(--el-color-primary-light-9,#ecf5ff);border-radius:calc(var(--el-border-radius-base, 4px) + 2px);display:flex;flex:1;gap:8px;min-width:0;outline:none;padding:4px 8px}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-cancel{flex-shrink:0}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-cancel:hover{color:var(--el-color-danger,#f56c6c)}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-wave{align-items:center;direction:rtl;display:flex;flex:1;gap:2px;height:22px;justify-content:flex-end;min-width:0;overflow:hidden}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-wave .fv-sender-recording-bar{background-color:var(--el-color-primary,#409eff);border-radius:1px;flex-shrink:0;min-height:2px;opacity:.75;width:2px}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-duration{color:var(--el-color-primary,#409eff);flex-shrink:0;font-size:var(--el-font-size-small,12px);font-variant-numeric:tabular-nums;min-width:3em;text-align:center}.fv-sender .fv-sender-body .fv-sender-recording .fv-sender-recording-confirm{flex-shrink:0}.fv-sender .fv-sender-body .fv-sender-input{display:flex;flex:1;min-width:0;position:relative}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea{background:transparent;border:none;box-sizing:border-box;color:var(--el-text-color-primary,#303133);flex:1;font:inherit;font-family:inherit;font-size:var(--el-font-size-base,14px);line-height:22px;min-width:0;outline:none;padding:4px 0;resize:none}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea::placeholder{color:var(--el-text-color-placeholder,#a8abb2)}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea:disabled{color:var(--el-text-color-disabled,#a8abb2);cursor:not-allowed}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-textarea[readonly]{cursor:default}.fv-sender .fv-sender-body .fv-sender-input .fv-sender-trigger-anchor{bottom:0;height:0;pointer-events:none;position:absolute;width:0}.fv-sender .fv-sender-body .fv-sender-actions{align-items:center;align-self:flex-end;display:flex;flex-shrink:0;gap:4px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-action-left{align-items:center;display:flex;gap:4px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech{color:var(--el-text-color-regular,#606266);padding:6px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech .el-icon{font-size:18px}.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech:not(.is-disabled):active,.fv-sender .fv-sender-body .fv-sender-actions .fv-sender-speech:not(.is-disabled):hover{background-color:transparent;color:var(--el-text-color-primary,#303133)}.fv-sender.variant-updown .fv-sender-row{align-items:stretch;flex-direction:column;gap:6px}.fv-sender.variant-updown .fv-sender-row .fv-sender-input{width:100%}.fv-sender.variant-updown .fv-sender-row .fv-sender-actions{align-self:flex-end;justify-content:flex-end}.fv-sender.variant-updown .fv-sender-row .fv-sender-actions:has(.fv-sender-action-left){align-self:stretch}.fv-sender.variant-updown .fv-sender-row .fv-sender-actions:has(.fv-sender-action-left) .fv-sender-action-left{margin-right:auto}.fv-sender.is-focused .fv-sender-body{border-color:var(--el-color-primary,#409eff)}.fv-sender.is-disabled .fv-sender-body{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-sender.has-shadow .fv-sender-body{box-shadow:0 8px 20px 0 var(--el-box-shadow-color,rgba(0,0,0,.08));transition:border-color .2s,box-shadow .2s}.fv-sender.has-shadow.is-focused .fv-sender-body{box-shadow:0 8px 24px 0 var(--el-box-shadow-color,rgba(0,0,0,.12))}.fv-sender .fv-sender-stop{--fv-sender-stop-icon-size:16px;--fv-sender-stop-ring-width:2px;--fv-sender-stop-ring-duration:1.1s;position:relative}.fv-sender .fv-sender-stop .el-icon{align-items:center;display:inline-flex;font-size:var(--fv-sender-stop-icon-size);justify-content:center}.fv-sender .fv-sender-stop .fv-stop-icon{display:block}.fv-sender .fv-sender-stop .fv-sender-stop-ring{height:100%;inset:0;overflow:visible;pointer-events:none;position:absolute;width:100%}.fv-sender .fv-sender-stop .fv-sender-stop-ring .fv-sender-stop-ring-rect{x:calc(var(--fv-sender-stop-ring-width)/2);y:calc(var(--fv-sender-stop-ring-width)/2);fill:none;stroke:rgb(255,255,255,var(--ring-alpha,.9));stroke-width:var(--fv-sender-stop-ring-width);stroke-dasharray:0 calc(100 - var(--ring-len, 10)) var(--ring-len,10) 0;animation:fv-sender-stop-spin var(--fv-sender-stop-ring-duration) linear infinite;height:calc(100% - var(--fv-sender-stop-ring-width));width:calc(100% - var(--fv-sender-stop-ring-width))}@media (prefers-reduced-motion:reduce){.fv-sender .fv-sender-stop .fv-sender-stop-ring-rect{animation:none}}.fv-sender .fv-sender-footer{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-base,14px);padding:6px 12px}@keyframes fv-sender-slide-down{0%{max-height:0;opacity:0}to{max-height:300px;opacity:1}}@keyframes fv-sender-stop-spin{to{stroke-dashoffset:-100}}.fv-mention-sender{position:relative}.fv-mention-sender .fv-mention-anchor{bottom:0;height:0;pointer-events:none;position:absolute;width:0}.fv-mention-popover .fv-mention-panel{max-height:260px;overflow-y:auto;padding:4px}.fv-mention-popover .fv-mention-title{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:4px 8px}.fv-mention-popover .fv-mention-loading{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);padding:8px;text-align:center}.fv-mention-popover .fv-mention-item{align-items:center;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-primary,#303133);cursor:pointer;display:flex;font-size:var(--el-font-size-base,14px);gap:8px;padding:6px 8px}.fv-mention-popover .fv-mention-item.is-active,.fv-mention-popover .fv-mention-item:hover{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-mention-popover .fv-mention-item .fv-mention-avatar{align-items:center;background-color:var(--el-fill-color,#e9e9eb);border-radius:50%;color:var(--el-text-color-regular,#606266);display:inline-flex;flex-shrink:0;font-size:var(--el-font-size-small,12px);height:24px;justify-content:center;overflow:hidden;width:24px}.fv-mention-popover .fv-mention-item .fv-mention-avatar img{height:100%;object-fit:cover;width:100%}.fv-mention-popover .fv-mention-item .fv-mention-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-editor-sender{box-sizing:border-box;display:flex;flex-direction:column;width:100%}.fv-editor-sender .fv-editor-header{animation:fv-editor-slide-down .3s ease;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);max-height:300px;overflow:hidden;padding:8px 12px}.fv-editor-sender .fv-editor-body{align-items:flex-end;background-color:var(--el-fill-color-blank,#fff);border:var(--el-border-width,1px) solid var(--el-border-color,#dcdfe6);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);display:flex;gap:8px;padding:8px 12px;transition:border-color .2s}.fv-editor-sender .fv-editor-body .fv-editor-prefix{align-items:center;align-self:center;display:flex;flex-shrink:0}.fv-editor-sender .fv-editor-body .fv-editor-input{display:flex;flex:1;min-width:0;position:relative}.fv-editor-sender .fv-editor-body .fv-editor-input .fv-editor-content{background:transparent;box-sizing:border-box;color:var(--el-text-color-primary,#303133);flex:1;font:inherit;font-family:inherit;font-size:var(--el-font-size-base,14px);line-height:22px;max-height:220px;min-width:0;outline:none;overflow-y:auto;padding:4px 0;white-space:pre-wrap;word-break:break-word}.fv-editor-sender .fv-editor-body .fv-editor-input .fv-editor-content:empty:before{color:var(--el-text-color-placeholder,#a8abb2);content:attr(data-placeholder);pointer-events:none}.fv-editor-sender .fv-editor-body .fv-editor-input .fv-editor-anchor{bottom:0;height:0;pointer-events:none;position:absolute;width:0}.fv-editor-sender .fv-editor-body .fv-editor-actions{align-items:center;align-self:flex-end;display:flex;flex-shrink:0;gap:4px}.fv-editor-sender .fv-editor-tag{align-items:center;background-color:var(--el-color-primary-light-9,#ecf5ff);border-radius:var(--el-border-radius-base,4px);box-sizing:border-box;color:var(--el-color-primary,#409eff);display:inline-flex;font-size:var(--el-font-size-base,14px);line-height:20px;margin:0 1px;max-width:100%;padding:0 6px;user-select:all;white-space:nowrap}.fv-editor-sender .fv-editor-tag.fv-editor-tag-inputTag{padding:0 2px}.fv-editor-sender .fv-editor-tag.fv-editor-tag-inputTag .fv-editor-tag-input{background:transparent;border:none;box-sizing:border-box;color:inherit;font:inherit;line-height:20px;outline:none;padding:0 4px;width:120px}.fv-editor-sender .fv-editor-tag.fv-editor-tag-inputTag .fv-editor-tag-input::placeholder{color:var(--el-text-color-placeholder,#a8abb2)}.fv-editor-sender .fv-editor-tag.fv-editor-tag-htmlTag{display:inline;user-select:text;white-space:normal}.fv-editor-sender.variant-updown .fv-editor-body{align-items:stretch;flex-direction:column;gap:6px}.fv-editor-sender.variant-updown .fv-editor-body .fv-editor-input{width:100%}.fv-editor-sender.variant-updown .fv-editor-body .fv-editor-actions{align-self:flex-end;justify-content:flex-end}.fv-editor-sender.device-h5 .fv-editor-body{padding:6px 10px}.fv-editor-sender.is-focused .fv-editor-body{border-color:var(--el-color-primary,#409eff)}.fv-editor-sender.is-disabled .fv-editor-body{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-editor-sender .fv-editor-footer{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-base,14px);padding:6px 12px}.fv-editor-mention-popover .fv-editor-mention-panel{max-height:260px;overflow-y:auto;padding:4px}.fv-editor-mention-popover .fv-editor-mention-title{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:4px 8px}.fv-editor-mention-popover .fv-editor-mention-loading{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);padding:8px;text-align:center}.fv-editor-mention-popover .fv-editor-mention-item{align-items:center;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-primary,#303133);cursor:pointer;display:flex;font-size:var(--el-font-size-base,14px);gap:8px;padding:6px 8px}.fv-editor-mention-popover .fv-editor-mention-item.is-active,.fv-editor-mention-popover .fv-editor-mention-item:hover{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-editor-mention-popover .fv-editor-mention-item .fv-editor-mention-avatar{align-items:center;background-color:var(--el-fill-color,#e9e9eb);border-radius:50%;color:var(--el-text-color-regular,#606266);display:inline-flex;flex-shrink:0;font-size:var(--el-font-size-small,12px);height:24px;justify-content:center;overflow:hidden;width:24px}.fv-editor-mention-popover .fv-editor-mention-item .fv-editor-mention-avatar img{height:100%;object-fit:cover;width:100%}.fv-editor-mention-popover .fv-editor-mention-item .fv-editor-mention-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-editor-tip-popover .fv-editor-tip-panel{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:6px 8px}.fv-editor-select-dialog .fv-editor-select-group+.fv-editor-select-group{margin-top:12px}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-title{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);font-weight:600;margin-bottom:8px}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-grid{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(96px,1fr))}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item{align-items:center;border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:var(--el-border-radius-base,4px);cursor:pointer;display:flex;flex-direction:column;gap:4px;padding:8px;transition:border-color .2s}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item:hover{border-color:var(--el-color-primary,#409eff)}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item .fv-editor-select-preview{border-radius:var(--el-border-radius-base,4px);height:56px;object-fit:cover;width:100%}.fv-editor-select-dialog .fv-editor-select-group .fv-editor-select-item .fv-editor-select-name{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-small,12px);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@keyframes fv-editor-slide-down{0%{max-height:0;opacity:0}to{max-height:300px;opacity:1}}.fv-thinking{background-color:var(--fv-thinking-bg,transparent);border-radius:var(--el-border-radius-base,4px);box-sizing:border-box;color:var(--fv-thinking-color,var(--el-text-color-regular,#606266));display:flex;flex-direction:column;width:100%}.fv-thinking .fv-thinking-toggle{align-items:center;background:none;border:none;color:inherit;cursor:pointer;display:inline-flex;font:inherit;font-size:var(--el-font-size-base,14px);gap:6px;line-height:22px;padding:4px 0;text-align:left;transition:color .2s;user-select:none}.fv-thinking .fv-thinking-toggle:hover{color:var(--fv-thinking-color,var(--el-color-primary,#409eff))}.fv-thinking .fv-thinking-toggle:focus{outline:none}.fv-thinking.is-disabled .fv-thinking-toggle{cursor:not-allowed;opacity:.6}.fv-thinking .fv-thinking-status-icon{align-items:center;display:inline-flex;height:16px;justify-content:center;width:16px}.fv-thinking .fv-thinking-status-icon .fv-thinking-dot{background-color:var(--el-color-primary,#409eff);border-radius:50%;height:8px;width:8px}.fv-thinking .fv-thinking-status-icon .is-loading{animation:fv-thinking-rotate 1s linear infinite;color:var(--el-color-primary,#409eff)}.fv-thinking .fv-thinking-status-icon .is-success{color:var(--el-color-success,#67c23a)}.fv-thinking .fv-thinking-status-icon .is-error{color:var(--el-color-danger,#f56c6c)}.fv-thinking .fv-thinking-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-thinking .fv-thinking-arrow{align-items:center;display:inline-flex;transition:transform .3s ease}.fv-thinking .fv-thinking-arrow.is-open{transform:rotate(180deg)}.fv-thinking .fv-thinking-content{box-sizing:border-box;color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-base,14px);line-height:22px;padding:8px 0 8px 22px;white-space:pre-wrap;word-break:break-word}@keyframes fv-thinking-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fv-chain{box-sizing:border-box;display:flex;font-size:var(--el-font-size-base,14px)}.fv-chain.is-vertical{flex-direction:column}.fv-chain.is-vertical .fv-chain-item{display:flex;gap:10px}.fv-chain.is-vertical .fv-chain-item:not(:last-child) .fv-chain-node:before{background-color:var(--el-border-color-lighter,#ebeef5);bottom:-4px;content:"";left:50%;margin-left:-1px;position:absolute;top:18px;width:2px}.fv-chain.is-horizontal{flex-direction:row;gap:24px}.fv-chain.is-horizontal .fv-chain-item{align-items:flex-start;display:flex;gap:6px}.fv-chain .fv-chain-node{align-items:center;display:inline-flex;flex-shrink:0;font-size:16px;height:18px;justify-content:center;position:relative;width:18px}.fv-chain .fv-chain-node .fv-chain-dot{background-color:var(--el-fill-color-blank,#fff);border:2px solid var(--el-border-color,#dcdfe6);border-radius:50%;box-sizing:border-box;height:8px;width:8px}.fv-chain .fv-chain-item.status-success .fv-chain-node{color:var(--el-color-success,#67c23a)}.fv-chain .fv-chain-item.status-success .fv-chain-node .fv-chain-dot{background-color:var(--el-color-success,#67c23a);border-color:var(--el-color-success,#67c23a)}.fv-chain .fv-chain-item.status-error .fv-chain-node{color:var(--el-color-danger,#f56c6c)}.fv-chain .fv-chain-item.status-error .fv-chain-node .fv-chain-dot{background-color:var(--el-color-danger,#f56c6c);border-color:var(--el-color-danger,#f56c6c)}.fv-chain .fv-chain-item.status-loading .fv-chain-node{color:var(--el-color-primary,#409eff)}.fv-chain .fv-chain-item.status-loading .fv-chain-node .is-loading{animation:fv-chain-rotate 1s linear infinite}.fv-chain .fv-chain-item.status-loading .fv-chain-node .fv-chain-dot{border-color:var(--el-color-primary,#409eff)}.fv-chain .fv-chain-item.status-pending .fv-chain-title{color:var(--el-text-color-placeholder,#a8abb2)}.fv-chain .fv-chain-main{flex:1;min-width:0;padding-bottom:4px}.fv-chain .fv-chain-main .fv-chain-title{color:var(--el-text-color-primary,#303133);line-height:22px}.fv-chain .fv-chain-main .fv-chain-description{color:var(--el-text-color-regular,#606266);font-size:var(--el-font-size-small,12px);line-height:20px;word-break:break-word}@keyframes fv-chain-rotate{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fv-welcome{box-sizing:border-box;flex-direction:column;padding:var(--el-main-padding,20px);text-align:center;width:100%}.fv-welcome,.fv-welcome-icon{align-items:center;display:flex;justify-content:center}.fv-welcome-icon{margin-bottom:16px}.fv-welcome-icon .fv-welcome-avatar{background-color:var(--el-fill-color-light,#f5f7fa);border-radius:calc(var(--el-border-radius-base, 4px) + 8px);color:var(--el-color-primary,#409eff);font-size:36px;height:72px;width:72px}.fv-welcome-name{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-extra-large,20px);font-weight:600;line-height:1.4;margin:0}.fv-welcome-description{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);margin:8px 0 0;max-width:480px;white-space:pre-wrap;word-break:break-word}.fv-prompts{box-sizing:border-box;width:100%}.fv-prompts .fv-prompts-title{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);margin-bottom:12px}.fv-prompts .fv-prompts-list{display:flex;flex-wrap:wrap;gap:12px}.fv-prompts .fv-prompt-item{background-color:var(--el-bg-color,#fff);border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);box-sizing:border-box;cursor:pointer;flex:1 1 200px;max-width:100%;padding:12px 14px;transition:background-color var(--el-transition-duration,.3s),border-color var(--el-transition-duration,.3s)}.fv-prompts .fv-prompt-item:hover:not(.is-disabled){background-color:var(--el-fill-color-light,#f5f7fa);border-color:var(--el-border-color,#dcdfe6)}.fv-prompts .fv-prompt-item:focus-visible:not(.is-disabled){border-color:var(--el-color-primary,#409eff);outline:none}.fv-prompts .fv-prompt-item.is-disabled{background-color:var(--el-fill-color-lighter,#fafafa);cursor:not-allowed;opacity:.6}.fv-prompts .fv-prompt-item.is-disabled,.fv-prompts .fv-prompt-item.is-disabled .fv-prompt-item-description,.fv-prompts .fv-prompt-item.is-disabled .fv-prompt-item-icon,.fv-prompts .fv-prompt-item.is-disabled .fv-prompt-item-label{color:var(--el-text-color-placeholder,#a8abb2)}.fv-prompts .fv-prompt-item .fv-prompt-item-main{align-items:flex-start;display:flex;gap:10px}.fv-prompts .fv-prompt-item .fv-prompt-item-icon{color:var(--el-color-primary,#409eff);flex-shrink:0;font-size:18px;margin-top:2px}.fv-prompts .fv-prompt-item .fv-prompt-item-text{flex:1;min-width:0}.fv-prompts .fv-prompt-item .fv-prompt-item-label{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);font-weight:500;line-height:var(--el-font-line-height-primary,24px);word-break:break-word}.fv-prompts .fv-prompt-item .fv-prompt-item-description{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);line-height:var(--el-font-line-height-primary,24px);margin-top:2px;word-break:break-word}.fv-files-card{align-items:center;background-color:var(--el-bg-color,#fff);border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);box-sizing:border-box;display:flex;gap:8px;max-width:100%;min-width:0;padding:8px 24px 8px 10px;position:relative;transition:border-color var(--el-transition-duration,.3s)}.fv-files-card .fv-files-card-icon{color:var(--el-color-primary,#409eff);flex-shrink:0;font-size:20px}.fv-files-card .fv-files-card-info{flex:1;min-width:0}.fv-files-card .fv-files-card-name{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-small,12px);line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-files-card .fv-files-card-size{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-extra-small,12px);line-height:16px;white-space:nowrap}.fv-files-card .fv-files-card-thumb{align-items:center;background-color:var(--el-fill-color-light,#f5f7fa);border-radius:var(--el-border-radius-base,4px);display:flex;flex-shrink:0;height:48px;justify-content:center;overflow:hidden;width:48px}.fv-files-card .fv-files-card-thumb .fv-files-card-img{display:block;height:100%;object-fit:cover;width:100%}.fv-files-card .fv-files-card-thumb .fv-files-card-thumb-placeholder{color:var(--el-text-color-placeholder,#a8abb2);font-size:20px}.fv-files-card .fv-files-card-status{align-items:center;background-color:var(--el-bg-color,#fff);border-radius:50%;bottom:-8px;display:flex;height:16px;justify-content:center;left:50%;position:absolute;transform:translateX(-50%);width:16px}.fv-files-card .fv-files-card-status .fv-files-card-loading{animation:fv-files-card-rotating 1.5s linear infinite;color:var(--el-color-primary,#409eff);font-size:14px}.fv-files-card .fv-files-card-remove{align-items:center;background-color:transparent;border:none;border-radius:50%;color:var(--el-text-color-secondary,#909399);cursor:pointer;display:flex;font-size:12px;height:18px;justify-content:center;opacity:0;padding:0;position:absolute;right:2px;top:2px;transition:opacity var(--el-transition-duration,.3s),color var(--el-transition-duration,.3s),background-color var(--el-transition-duration,.3s);width:18px}.fv-files-card .fv-files-card-remove:hover{background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-color-danger,#f56c6c)}.fv-files-card:hover .fv-files-card-remove{opacity:1}.fv-files-card.is-error{border-color:var(--el-color-danger,#f56c6c)}.fv-files-card.is-error .fv-files-card-name{color:var(--el-color-danger,#f56c6c)}@keyframes fv-files-card-rotating{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.fv-attachments{align-items:flex-start;box-sizing:border-box;display:flex;gap:8px;width:100%}.fv-attachments .fv-attachments-input{display:none}.fv-attachments .fv-attachments-trigger{align-items:center;background-color:transparent;border:none;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-secondary,#909399);cursor:pointer;display:flex;flex-shrink:0;font-size:16px;height:32px;justify-content:center;padding:0;transition:color var(--el-transition-duration,.3s),background-color var(--el-transition-duration,.3s);width:32px}.fv-attachments .fv-attachments-trigger:hover:not(:disabled){background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-color-primary,#409eff)}.fv-attachments .fv-attachments-trigger.is-full,.fv-attachments .fv-attachments-trigger:disabled{color:var(--el-text-color-placeholder,#a8abb2);cursor:not-allowed}.fv-attachments .fv-attachments-list{display:flex;flex-wrap:wrap;gap:8px;min-width:0}.fv-attachments .fv-attachments-item{align-items:center;display:flex;min-width:0;position:relative}.fv-attachments .fv-attachments-item .fv-files-card{max-width:240px}.fv-attachments .fv-attachments-item .fv-attachments-retry{align-items:center;background-color:transparent;border:none;border-radius:50%;color:var(--el-text-color-secondary,#909399);cursor:pointer;display:flex;font-size:14px;height:20px;justify-content:center;margin-left:4px;padding:0;transition:color var(--el-transition-duration,.3s),background-color var(--el-transition-duration,.3s);width:20px}.fv-attachments .fv-attachments-item .fv-attachments-retry:hover{background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-color-primary,#409eff)}.fv-attachments .fv-attachments-tip{color:var(--el-text-color-placeholder,#a8abb2);flex:1;font-size:var(--el-font-size-extra-small,12px);line-height:32px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-conversations{box-sizing:border-box;overflow-y:auto;width:100%}.fv-conversations .fv-conversations-group .fv-conversations-group-title{background-color:var(--el-bg-color,#fff);color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-extra-small,12px);line-height:20px;padding:8px 12px 4px;position:sticky;top:0;z-index:1}.fv-conversations .fv-conversations-item{align-items:center;border-radius:var(--el-border-radius-base,4px);cursor:pointer;display:flex;gap:4px;padding:0 8px 0 12px;transition:background-color .2s;user-select:none}.fv-conversations .fv-conversations-item:hover{background-color:var(--el-fill-color-light,#f5f7fa)}.fv-conversations .fv-conversations-item:hover .fv-conversations-menu-btn{opacity:1;pointer-events:auto}.fv-conversations .fv-conversations-item.is-active{background-color:var(--el-color-primary-light-9,#ecf5ff);color:var(--el-color-primary,#409eff)}.fv-conversations .fv-conversations-item.is-active .fv-conversations-item-label{color:var(--el-color-primary,#409eff);font-weight:600}.fv-conversations .fv-conversations-item.is-disabled{color:var(--el-text-color-disabled,#a8abb2);cursor:not-allowed}.fv-conversations .fv-conversations-item.is-disabled .fv-conversations-item-label{color:var(--el-text-color-disabled,#a8abb2)}.fv-conversations .fv-conversations-item.is-disabled:hover{background-color:transparent}.fv-conversations .fv-conversations-item .fv-conversations-item-content{flex:1;min-width:0;padding:9px 0}.fv-conversations .fv-conversations-item .fv-conversations-item-content .fv-conversations-item-label{color:var(--el-text-color-regular,#606266);display:block;font-size:var(--el-font-size-base,14px);line-height:22px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-conversations .fv-conversations-item .fv-conversations-menu-btn{align-items:center;background:transparent;border:none;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-secondary,#909399);cursor:pointer;display:inline-flex;flex-shrink:0;height:24px;justify-content:center;opacity:0;padding:0;pointer-events:none;transition:opacity .2s;width:24px}.fv-conversations .fv-conversations-item .fv-conversations-menu-btn:hover{background-color:var(--el-fill-color,#f0f2f5);color:var(--el-text-color-primary,#303133)}.fv-conversations.show-menu-always .fv-conversations-item .fv-conversations-menu-btn{opacity:1;pointer-events:auto}.fv-msg{align-items:flex-start;box-sizing:border-box;display:flex;gap:12px;padding:8px 0;width:100%}.fv-msg .fv-msg-avatar{background-color:var(--el-fill-color-light,#f5f7fa);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);color:var(--el-text-color-secondary,#909399);flex-shrink:0;font-size:18px;height:32px;width:32px}.fv-msg .fv-msg-avatar,.fv-msg .fv-msg-avatar-bot{align-items:center;display:flex;justify-content:center}.fv-msg .fv-msg-avatar-bot{background-color:var(--el-color-primary,#409eff);border-radius:inherit;color:#fff;height:100%;width:100%}.fv-msg .fv-msg-avatar-img{border-radius:inherit;display:block;height:100%;object-fit:cover;width:100%}.fv-msg.is-user .fv-msg-avatar{background-color:var(--el-color-primary-light-8,#d9ecff);color:var(--el-color-primary,#409eff);order:2}.fv-msg .fv-msg-main{align-items:flex-start;display:flex;flex:1;flex-direction:column;min-width:0}.fv-msg .fv-msg-main .fv-msg-header{align-items:center;color:var(--el-text-color-secondary,#909399);display:flex;font-size:var(--el-font-size-small,12px);gap:8px;margin-bottom:2px}.fv-msg .fv-msg-main .fv-msg-header .fv-msg-model{background-color:var(--el-fill-color,#f0f2f5);border-radius:var(--el-border-radius-base,4px);line-height:18px;padding:0 6px}.fv-msg .fv-msg-main .fv-msg-files{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:4px}.fv-msg .fv-msg-main .fv-msg-files .fv-msg-file{align-items:center;border:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-regular,#606266);display:inline-flex;font-size:var(--el-font-size-small,12px);padding:4px 8px}.fv-msg .fv-msg-main .fv-msg-files .fv-msg-file .fv-msg-file-img{border-radius:var(--el-border-radius-base,4px);max-height:64px;max-width:64px;object-fit:cover}.fv-msg .fv-msg-main .fv-msg-tools.fv-chain{font-size:var(--el-font-size-base,14px)}.fv-msg .fv-msg-main .fv-msg-tools.fv-chain .fv-chain-item:not(:last-child){padding-bottom:2px}.fv-msg .fv-msg-main .fv-msg-tools.fv-chain .fv-chain-item:not(:last-child) .fv-chain-node:before{background-color:var(--el-border-color-lighter,#ebeef5);bottom:-4px;content:"";left:50%;margin-left:-1px;position:absolute;top:18px;width:2px}.fv-msg .fv-msg-main .fv-msg-tools.fv-chain .fv-chain-title{color:var(--el-text-color-primary,#303133)}.fv-msg .fv-msg-main .fv-msg-tools.fv-chain .fv-chain-description{color:var(--el-text-color-secondary,#909399)}.fv-msg .fv-msg-main .fv-msg-content{color:var(--el-text-color-primary,#303133);font-size:var(--el-font-size-base,14px);line-height:var(--el-font-line-height-primary,24px);max-width:100%;min-width:0;word-break:break-word}.fv-msg .fv-msg-main .fv-msg-content .fv-msg-error{color:var(--el-color-danger,#f56c6c)}.fv-msg .fv-msg-main .fv-msg-content .fv-msg-pending{align-items:center;display:inline-flex;gap:4px;padding:4px 0}.fv-msg .fv-msg-main .fv-msg-content .fv-msg-pending .fv-msg-dot{animation:fv-msg-blink 1s infinite;background-color:var(--el-text-color-secondary,#909399);border-radius:50%;height:6px;width:6px}.fv-msg .fv-msg-main .fv-msg-content-user{background-color:var(--el-fill-color-light,#f5f7fa);border-radius:calc(var(--el-border-radius-base, 4px) + 4px);padding:8px 12px;white-space:pre-wrap}.fv-msg.is-user{flex-direction:row;justify-content:flex-end}.fv-msg.is-user .fv-msg-main{align-items:flex-end}.fv-msg .fv-msg-actions{align-items:center;display:flex;gap:2px;margin-top:2px}.fv-msg .fv-msg-actions .el-button+.el-button{margin-left:0}.fv-msg .fv-msg-actions .fv-msg-branch{align-items:center;display:inline-flex;gap:2px;margin-left:6px}.fv-msg .fv-msg-actions .fv-msg-branch .fv-msg-branch-label{color:var(--el-text-color-secondary,#909399);font-size:var(--el-font-size-small,12px);padding:0 2px}.fv-msg.is-user .fv-msg-actions{opacity:0;pointer-events:none;transition:opacity .15s}.fv-msg.is-user .fv-msg-actions .fv-msg-branch{margin-left:0}.fv-msg.is-user:focus-within .fv-msg-actions,.fv-msg.is-user:hover .fv-msg-actions{opacity:1;pointer-events:auto}@keyframes fv-msg-blink{0%,to{opacity:.3}50%{opacity:1}}.fv-messages{box-sizing:border-box;display:flex;flex:1;flex-direction:column;min-height:0;width:100%}.fv-messages .fv-messages-scroll{box-sizing:border-box;flex:1;min-height:0;overflow-y:auto;padding:0 16px}.fv-messages .fv-messages-inner{margin:0 auto;max-width:var(--fv-messages-max-width,none);position:relative}.fv-messages .fv-messages-empty{align-items:center;box-sizing:border-box;display:flex;flex:1;flex-direction:column;justify-content:center;padding:32px 16px}.fv-messages .fv-messages-empty .fv-messages-prompts{margin-top:8px;max-width:640px;width:100%}.fv-messages .fv-messages-back{bottom:16px;box-shadow:var(--el-box-shadow-light,0 0 12px rgba(0,0,0,.12));float:right;margin-right:16px;margin-top:-40px;pointer-events:auto;position:sticky;z-index:1}.fv-messages .fv-messages-back .fv-messages-back-icon{font-size:16px;line-height:1}.fv-messages-back-fade-enter-active,.fv-messages-back-fade-leave-active{transition:opacity .2s ease}.fv-messages-back-fade-enter-from,.fv-messages-back-fade-leave-to{opacity:0}.fv-ai-chat{background-color:var(--el-bg-color,#fff);box-sizing:border-box;color:var(--el-text-color-primary,#303133);display:flex;flex-direction:column;height:100%;min-height:0;width:100%}.fv-ai-chat .fv-ai-chat-header{align-items:center;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);display:flex;flex-shrink:0;gap:12px;justify-content:space-between;padding:8px 16px}.fv-ai-chat .fv-ai-chat-header .fv-ai-chat-title{font-size:var(--el-font-size-base,14px);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fv-ai-chat .fv-ai-chat-header .fv-ai-chat-models{flex-shrink:0;width:220px}.fv-ai-chat .fv-ai-chat-body{display:flex;flex:1;min-height:0;overflow:hidden}.fv-ai-chat .fv-ai-chat-footer{flex-shrink:0;padding:8px 16px 12px}.fv-ai-chat.is-center-welcome .fv-ai-chat-body{flex:0 1 auto;margin-top:auto;min-height:0}.fv-ai-chat.is-center-welcome .fv-ai-chat-footer{margin-bottom:auto}html.dark .fv-ai-chat{background-color:var(--el-bg-color,#141414)}.fv-artifacts{background-color:var(--el-bg-color,#fff);border-left:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);box-sizing:border-box;display:flex;flex-direction:column;flex-shrink:0;max-width:60%;overflow:hidden;width:420px}.fv-artifacts .fv-artifacts-tabs{align-items:center;border-bottom:var(--el-border-width,1px) solid var(--el-border-color-lighter,#ebeef5);display:flex;flex-shrink:0;gap:4px;overflow-x:auto;padding:6px 8px}.fv-artifacts .fv-artifacts-tabs .fv-artifact-tab{background:transparent;border:none;border-radius:var(--el-border-radius-base,4px);color:var(--el-text-color-regular,#606266);cursor:pointer;flex-shrink:0;font-size:var(--el-font-size-small,12px);line-height:1.4;padding:4px 10px;white-space:nowrap}.fv-artifacts .fv-artifacts-tabs .fv-artifact-tab:hover{background-color:var(--el-fill-color-light,#f5f7fa);color:var(--el-text-color-primary,#303133)}.fv-artifacts .fv-artifacts-tabs .fv-artifact-tab.is-active{background-color:var(--el-color-primary-light-9,#ecf5ff);color:var(--el-color-primary,#409eff)}.fv-artifacts .fv-artifacts-tabs .fv-artifacts-spacer{flex:1}.fv-artifacts .fv-artifacts-frame{background-color:var(--el-bg-color-page,#f2f3f5);border:none;flex:1;min-height:0;width:100%}html.dark .fv-artifacts{background-color:var(--el-bg-color,#141414)}
package/es/index.mjs CHANGED
@@ -5,7 +5,7 @@ import DOMPurify from 'dompurify';
5
5
  import Prism$1 from 'prismjs';
6
6
  import { ElAvatar, ElButton, ElIcon, ElPopover, ElMessage, ElDialog, ElDropdown, ElDropdownMenu, ElDropdownItem, ElMessageBox, ElTooltip, ElSelect, ElOption } from 'element-plus';
7
7
  import * as ElementPlusIconsVue from '@element-plus/icons-vue';
8
- import { ArrowDown, Close, Check, Delete, Microphone, Promotion, VideoPause, Loading, SuccessFilled, CircleCloseFilled, ChatDotRound, Cpu, Cellphone, Link, Folder, Headset, Film, Monitor, DataAnalysis, Document, Notebook, Picture, Paperclip, RefreshRight, MoreFilled, User, DocumentCopy, ArrowUp, CopyDocument, Download, FullScreen } from '@element-plus/icons-vue';
8
+ import { ArrowDown, Close, Check, Delete, Microphone, Promotion, VideoPause, Loading, SuccessFilled, CircleCloseFilled, ChatDotRound, Cpu, Cellphone, Link, Folder, Headset, Film, Monitor, DataAnalysis, Document, Notebook, Picture, Paperclip, RefreshRight, MoreFilled, User, DocumentCopy, ArrowUp, Bottom, CopyDocument, Download, FullScreen } from '@element-plus/icons-vue';
9
9
 
10
10
  function unwrapPlugin(plugin) {
11
11
  const candidate = plugin && typeof plugin === "object" && "default" in plugin ? plugin.default : plugin;
@@ -5615,6 +5615,7 @@ function createMessageTree(initial) {
5615
5615
  role: node.role,
5616
5616
  content: node.content,
5617
5617
  reasoning: node.reasoning,
5618
+ toolSteps: node.toolSteps ? node.toolSteps.map((s) => ({ ...s })) : void 0,
5618
5619
  files: node.files ? [...node.files] : void 0,
5619
5620
  modelIdx: node.modelIdx,
5620
5621
  model: node.model,
@@ -5895,6 +5896,17 @@ ${fileParts.join("\n")}` });
5895
5896
  msgs.edit(assistantId, { backendId: id });
5896
5897
  },
5897
5898
  onTool: (ev) => {
5899
+ const steps = [...msgs.messages.value[assistantId]?.toolSteps ?? []];
5900
+ if (ev.status === "start") {
5901
+ steps.push({
5902
+ key: `${ev.toolName}-${steps.length}`,
5903
+ title: options.toolStepLabel ? options.toolStepLabel(ev.toolName) : ev.toolName,
5904
+ status: "loading"
5905
+ });
5906
+ } else if (steps.length) {
5907
+ steps[steps.length - 1] = { ...steps[steps.length - 1], status: "success" };
5908
+ }
5909
+ msgs.edit(assistantId, { toolSteps: steps });
5898
5910
  options.onToolEvent?.(ev);
5899
5911
  },
5900
5912
  onDone: () => {
@@ -6029,7 +6041,7 @@ const _hoisted_10 = {
6029
6041
  class: "fv-msg-file-name"
6030
6042
  };
6031
6043
  const _hoisted_11 = {
6032
- key: 3,
6044
+ key: 4,
6033
6045
  class: "fv-msg-content"
6034
6046
  };
6035
6047
  const _hoisted_12 = {
@@ -6041,11 +6053,11 @@ const _hoisted_13 = {
6041
6053
  class: "fv-msg-pending"
6042
6054
  };
6043
6055
  const _hoisted_14 = {
6044
- key: 4,
6056
+ key: 5,
6045
6057
  class: "fv-msg-content fv-msg-content-user"
6046
6058
  };
6047
6059
  const _hoisted_15 = {
6048
- key: 5,
6060
+ key: 6,
6049
6061
  class: "fv-msg-actions"
6050
6062
  };
6051
6063
  const _hoisted_16 = {
@@ -6083,6 +6095,19 @@ var _sfc_main$3 = /* @__PURE__ */ defineComponent({
6083
6095
  return "end";
6084
6096
  });
6085
6097
  const hasReasoning = computed(() => !!props.message.reasoning);
6098
+ const hasToolSteps = computed(() => (props.message.toolSteps?.length ?? 0) > 0);
6099
+ const toolChainItems = computed(() => {
6100
+ const steps = props.message.toolSteps ?? [];
6101
+ const running = props.message.status === "pending" || props.message.status === "streaming";
6102
+ return steps.map((s) => {
6103
+ const loading = running && s.status !== "error" && s.status !== "success";
6104
+ return {
6105
+ ...s,
6106
+ status: loading ? "loading" : s.status ?? "success",
6107
+ title: `${loading ? "\u6B63\u5728\u67E5\u8BE2" : "\u5DF2\u67E5\u8BE2"}${s.title ?? ""}`
6108
+ };
6109
+ });
6110
+ });
6086
6111
  const modelLabel = computed(() => props.message.model ?? "");
6087
6112
  function onCopy() {
6088
6113
  emit("copy", props.message);
@@ -6200,9 +6225,15 @@ var _sfc_main$3 = /* @__PURE__ */ defineComponent({
6200
6225
  ))
6201
6226
  ])
6202
6227
  ])) : createCommentVNode("v-if", true),
6228
+ createCommentVNode(" \u5DE5\u5177\u8C03\u7528\u8F68\u8FF9(assistant \u542B toolSteps \u65F6):\u7EB5\u5411\u6B65\u9AA4\u94FE,Thinking \u4E4B\u4E0B\u6B63\u6587\u4E4B\u4E0A "),
6229
+ !isUser.value && hasToolSteps.value ? (openBlock(), createBlock(_sfc_main$9, {
6230
+ key: 2,
6231
+ class: "fv-msg-tools",
6232
+ items: toolChainItems.value
6233
+ }, null, 8, ["items"])) : createCommentVNode("v-if", true),
6203
6234
  createCommentVNode(" \u601D\u8003\u94FE\u6298\u53E0(assistant \u542B reasoning \u65F6) "),
6204
6235
  !isUser.value && hasReasoning.value ? (openBlock(), createBlock(_sfc_main$a, {
6205
- key: 2,
6236
+ key: 3,
6206
6237
  content: __props.message.reasoning,
6207
6238
  status: thinkingStatus.value,
6208
6239
  "auto-collapse": __props.autoCollapse
@@ -6420,6 +6451,8 @@ var _sfc_main$2 = /* @__PURE__ */ defineComponent({
6420
6451
  suggestions: { type: Array, required: false, default: () => [] },
6421
6452
  suggestionsTitle: { type: String, required: false, default: "" },
6422
6453
  scrollThreshold: { type: Number, required: false, default: 40 },
6454
+ showScrollButton: { type: Boolean, required: false, default: true },
6455
+ scrollButtonThreshold: { type: Number, required: false, default: 100 },
6423
6456
  showActions: { type: Boolean, required: false, default: true },
6424
6457
  showBranchSwitch: { type: Boolean, required: false, default: true },
6425
6458
  showUserAvatar: { type: Boolean, required: false, default: true },
@@ -6454,8 +6487,14 @@ var _sfc_main$2 = /* @__PURE__ */ defineComponent({
6454
6487
  function scrollToBottomIfNear() {
6455
6488
  if (distanceFromBottom() <= props.scrollThreshold) nextTick(() => scrollToBottom());
6456
6489
  }
6490
+ const isAwayFromBottom = ref(false);
6491
+ function onScroll() {
6492
+ isAwayFromBottom.value = distanceFromBottom() > props.scrollButtonThreshold;
6493
+ }
6494
+ watch(() => props.scrollButtonThreshold, onScroll);
6457
6495
  onMounted(() => {
6458
6496
  if (!isEmpty.value) nextTick(() => scrollToBottom(false));
6497
+ onScroll();
6459
6498
  });
6460
6499
  watch(() => props.messages.length, (nv, ov) => {
6461
6500
  if (nv > (ov ?? 0)) scrollToBottomIfNear();
@@ -6532,7 +6571,8 @@ var _sfc_main$2 = /* @__PURE__ */ defineComponent({
6532
6571
  {
6533
6572
  ref_key: "scrollRef",
6534
6573
  ref: scrollRef,
6535
- class: "fv-messages-scroll"
6574
+ class: "fv-messages-scroll",
6575
+ onScrollPassive: onScroll
6536
6576
  },
6537
6577
  [
6538
6578
  createElementVNode("div", _hoisted_3$2, [
@@ -6607,11 +6647,44 @@ var _sfc_main$2 = /* @__PURE__ */ defineComponent({
6607
6647
  }),
6608
6648
  128
6609
6649
  /* KEYED_FRAGMENT */
6610
- ))
6650
+ )),
6651
+ createCommentVNode(" \u6EDA\u5230\u5E95\u90E8\u60AC\u6D6E\u6309\u94AE:\u5728 fv-messages-inner \u5185,\u968F\u5185\u5BB9\u5BBD\u5EA6\u7EA6\u675F\u5C42\u5B9A\u4F4D(\u5BBD\u5C4F\u65F6\u4E0D\u8D34\u89C6\u53E3\u53F3\u7F18);\r\n \u8DDD\u5E95\u8D85\u8FC7 scrollButtonThreshold \u663E\u793A(\u7A7A\u6001\u4E0D\u6E32\u67D3);\r\n scroll-button \u63D2\u69FD\u6574\u4F53\u8986\u76D6\u6309\u94AE,scroll-button-icon \u63D2\u69FD\u4EC5\u8986\u76D6\u56FE\u6807\u5185\u5BB9 "),
6652
+ createVNode(Transition, { name: "fv-messages-back-fade" }, {
6653
+ default: withCtx(() => [
6654
+ renderSlot(_ctx.$slots, "scroll-button", {
6655
+ scrollToBottom,
6656
+ awayFromBottom: isAwayFromBottom.value
6657
+ }, () => [
6658
+ __props.showScrollButton && !isEmpty.value && isAwayFromBottom.value ? (openBlock(), createBlock(unref(ElButton), {
6659
+ key: 0,
6660
+ class: "fv-messages-back",
6661
+ circle: "",
6662
+ "aria-label": "\u6EDA\u52A8\u5230\u5E95\u90E8",
6663
+ onClick: _cache[0] || (_cache[0] = ($event) => scrollToBottom())
6664
+ }, {
6665
+ default: withCtx(() => [
6666
+ createVNode(unref(ElIcon), { class: "fv-messages-back-icon" }, {
6667
+ default: withCtx(() => [
6668
+ renderSlot(_ctx.$slots, "scroll-button-icon", {}, () => [
6669
+ createVNode(unref(Bottom))
6670
+ ])
6671
+ ]),
6672
+ _: 3
6673
+ /* FORWARDED */
6674
+ })
6675
+ ]),
6676
+ _: 3
6677
+ /* FORWARDED */
6678
+ })) : createCommentVNode("v-if", true)
6679
+ ])
6680
+ ]),
6681
+ _: 3
6682
+ /* FORWARDED */
6683
+ })
6611
6684
  ])
6612
6685
  ],
6613
- 512
6614
- /* NEED_PATCH */
6686
+ 544
6687
+ /* NEED_HYDRATION, NEED_PATCH */
6615
6688
  )
6616
6689
  ],
6617
6690
  2112
@@ -6896,6 +6969,8 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
6896
6969
  title: { type: String, required: false, default: "" },
6897
6970
  showHeader: { type: Boolean, required: false, default: false },
6898
6971
  centerWelcome: { type: Boolean, required: false, default: true },
6972
+ showScrollButton: { type: Boolean, required: false, default: true },
6973
+ scrollButtonThreshold: { type: Number, required: false, default: 100 },
6899
6974
  showUserAvatar: { type: Boolean, required: false, default: true },
6900
6975
  showUserName: { type: Boolean, required: false, default: true },
6901
6976
  showAssistantAvatar: { type: Boolean, required: false, default: true },
@@ -6905,6 +6980,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
6905
6980
  userName: { type: String, required: false, default: "" },
6906
6981
  assistantName: { type: String, required: false, default: "" },
6907
6982
  placeholder: { type: String, required: false, default: "" },
6983
+ toolStepLabel: { type: Function, required: false, default: void 0 },
6908
6984
  senderShadow: { type: Boolean, required: false, default: true },
6909
6985
  suggestions: { type: Array, required: false, default: () => [] },
6910
6986
  features: { type: Object, required: false, default: () => ({}) },
@@ -6948,6 +7024,7 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
6948
7024
  adapter: resolveAdapter,
6949
7025
  models: () => isMultiple.value && selectedModels.value.length ? selectedModels.value : [""],
6950
7026
  initial: { messages: initialTable, currentId: initialId },
7027
+ toolStepLabel: props.toolStepLabel,
6951
7028
  onToolEvent: (ev) => emit("tool-event", ev)
6952
7029
  });
6953
7030
  const { send, stop: stopChat, regenerate: regenerateChat, msgs, isLoading } = chat;
@@ -7167,6 +7244,8 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
7167
7244
  nodes: unref(nodeTable),
7168
7245
  name: __props.title,
7169
7246
  suggestions: __props.suggestions,
7247
+ "show-scroll-button": __props.showScrollButton,
7248
+ "scroll-button-threshold": __props.scrollButtonThreshold,
7170
7249
  "show-user-avatar": __props.showUserAvatar,
7171
7250
  "show-user-name": __props.showUserName,
7172
7251
  "show-assistant-avatar": __props.showAssistantAvatar,
@@ -7231,8 +7310,22 @@ var _sfc_main = /* @__PURE__ */ defineComponent({
7231
7310
  renderSlot(_ctx.$slots, "empty")
7232
7311
  ]),
7233
7312
  key: "6"
7313
+ } : void 0,
7314
+ _ctx.$slots["scroll-button"] ? {
7315
+ name: "scroll-button",
7316
+ fn: withCtx((scope) => [
7317
+ renderSlot(_ctx.$slots, "scroll-button", normalizeProps(guardReactiveProps(scope)))
7318
+ ]),
7319
+ key: "7"
7320
+ } : void 0,
7321
+ _ctx.$slots["scroll-button-icon"] ? {
7322
+ name: "scroll-button-icon",
7323
+ fn: withCtx(() => [
7324
+ renderSlot(_ctx.$slots, "scroll-button-icon")
7325
+ ]),
7326
+ key: "8"
7234
7327
  } : void 0
7235
- ]), 1032, ["messages", "nodes", "name", "suggestions", "show-user-avatar", "show-user-name", "show-assistant-avatar", "show-assistant-name", "user-avatar", "assistant-avatar", "user-name", "assistant-name"]),
7328
+ ]), 1032, ["messages", "nodes", "name", "suggestions", "show-scroll-button", "scroll-button-threshold", "show-user-avatar", "show-user-name", "show-assistant-avatar", "show-assistant-name", "user-avatar", "assistant-avatar", "user-name", "assistant-name"]),
7236
7329
  __props.features?.artifacts && artifacts.value.length ? (openBlock(), createBlock(_sfc_main$1, {
7237
7330
  key: 0,
7238
7331
  artifacts: artifacts.value,
package/lib/index.js CHANGED
@@ -5631,6 +5631,7 @@
5631
5631
  role: node.role,
5632
5632
  content: node.content,
5633
5633
  reasoning: node.reasoning,
5634
+ toolSteps: node.toolSteps ? node.toolSteps.map((s) => ({ ...s })) : void 0,
5634
5635
  files: node.files ? [...node.files] : void 0,
5635
5636
  modelIdx: node.modelIdx,
5636
5637
  model: node.model,
@@ -5911,6 +5912,17 @@ ${fileParts.join("\n")}` });
5911
5912
  msgs.edit(assistantId, { backendId: id });
5912
5913
  },
5913
5914
  onTool: (ev) => {
5915
+ const steps = [...msgs.messages.value[assistantId]?.toolSteps ?? []];
5916
+ if (ev.status === "start") {
5917
+ steps.push({
5918
+ key: `${ev.toolName}-${steps.length}`,
5919
+ title: options.toolStepLabel ? options.toolStepLabel(ev.toolName) : ev.toolName,
5920
+ status: "loading"
5921
+ });
5922
+ } else if (steps.length) {
5923
+ steps[steps.length - 1] = { ...steps[steps.length - 1], status: "success" };
5924
+ }
5925
+ msgs.edit(assistantId, { toolSteps: steps });
5914
5926
  options.onToolEvent?.(ev);
5915
5927
  },
5916
5928
  onDone: () => {
@@ -6045,7 +6057,7 @@ ${fileParts.join("\n")}` });
6045
6057
  class: "fv-msg-file-name"
6046
6058
  };
6047
6059
  const _hoisted_11 = {
6048
- key: 3,
6060
+ key: 4,
6049
6061
  class: "fv-msg-content"
6050
6062
  };
6051
6063
  const _hoisted_12 = {
@@ -6057,11 +6069,11 @@ ${fileParts.join("\n")}` });
6057
6069
  class: "fv-msg-pending"
6058
6070
  };
6059
6071
  const _hoisted_14 = {
6060
- key: 4,
6072
+ key: 5,
6061
6073
  class: "fv-msg-content fv-msg-content-user"
6062
6074
  };
6063
6075
  const _hoisted_15 = {
6064
- key: 5,
6076
+ key: 6,
6065
6077
  class: "fv-msg-actions"
6066
6078
  };
6067
6079
  const _hoisted_16 = {
@@ -6099,6 +6111,19 @@ ${fileParts.join("\n")}` });
6099
6111
  return "end";
6100
6112
  });
6101
6113
  const hasReasoning = vue.computed(() => !!props.message.reasoning);
6114
+ const hasToolSteps = vue.computed(() => (props.message.toolSteps?.length ?? 0) > 0);
6115
+ const toolChainItems = vue.computed(() => {
6116
+ const steps = props.message.toolSteps ?? [];
6117
+ const running = props.message.status === "pending" || props.message.status === "streaming";
6118
+ return steps.map((s) => {
6119
+ const loading = running && s.status !== "error" && s.status !== "success";
6120
+ return {
6121
+ ...s,
6122
+ status: loading ? "loading" : s.status ?? "success",
6123
+ title: `${loading ? "\u6B63\u5728\u67E5\u8BE2" : "\u5DF2\u67E5\u8BE2"}${s.title ?? ""}`
6124
+ };
6125
+ });
6126
+ });
6102
6127
  const modelLabel = vue.computed(() => props.message.model ?? "");
6103
6128
  function onCopy() {
6104
6129
  emit("copy", props.message);
@@ -6216,9 +6241,15 @@ ${fileParts.join("\n")}` });
6216
6241
  ))
6217
6242
  ])
6218
6243
  ])) : vue.createCommentVNode("v-if", true),
6244
+ vue.createCommentVNode(" \u5DE5\u5177\u8C03\u7528\u8F68\u8FF9(assistant \u542B toolSteps \u65F6):\u7EB5\u5411\u6B65\u9AA4\u94FE,Thinking \u4E4B\u4E0B\u6B63\u6587\u4E4B\u4E0A "),
6245
+ !isUser.value && hasToolSteps.value ? (vue.openBlock(), vue.createBlock(_sfc_main$9, {
6246
+ key: 2,
6247
+ class: "fv-msg-tools",
6248
+ items: toolChainItems.value
6249
+ }, null, 8, ["items"])) : vue.createCommentVNode("v-if", true),
6219
6250
  vue.createCommentVNode(" \u601D\u8003\u94FE\u6298\u53E0(assistant \u542B reasoning \u65F6) "),
6220
6251
  !isUser.value && hasReasoning.value ? (vue.openBlock(), vue.createBlock(_sfc_main$a, {
6221
- key: 2,
6252
+ key: 3,
6222
6253
  content: __props.message.reasoning,
6223
6254
  status: thinkingStatus.value,
6224
6255
  "auto-collapse": __props.autoCollapse
@@ -6436,6 +6467,8 @@ ${fileParts.join("\n")}` });
6436
6467
  suggestions: { type: Array, required: false, default: () => [] },
6437
6468
  suggestionsTitle: { type: String, required: false, default: "" },
6438
6469
  scrollThreshold: { type: Number, required: false, default: 40 },
6470
+ showScrollButton: { type: Boolean, required: false, default: true },
6471
+ scrollButtonThreshold: { type: Number, required: false, default: 100 },
6439
6472
  showActions: { type: Boolean, required: false, default: true },
6440
6473
  showBranchSwitch: { type: Boolean, required: false, default: true },
6441
6474
  showUserAvatar: { type: Boolean, required: false, default: true },
@@ -6470,8 +6503,14 @@ ${fileParts.join("\n")}` });
6470
6503
  function scrollToBottomIfNear() {
6471
6504
  if (distanceFromBottom() <= props.scrollThreshold) vue.nextTick(() => scrollToBottom());
6472
6505
  }
6506
+ const isAwayFromBottom = vue.ref(false);
6507
+ function onScroll() {
6508
+ isAwayFromBottom.value = distanceFromBottom() > props.scrollButtonThreshold;
6509
+ }
6510
+ vue.watch(() => props.scrollButtonThreshold, onScroll);
6473
6511
  vue.onMounted(() => {
6474
6512
  if (!isEmpty.value) vue.nextTick(() => scrollToBottom(false));
6513
+ onScroll();
6475
6514
  });
6476
6515
  vue.watch(() => props.messages.length, (nv, ov) => {
6477
6516
  if (nv > (ov ?? 0)) scrollToBottomIfNear();
@@ -6548,7 +6587,8 @@ ${fileParts.join("\n")}` });
6548
6587
  {
6549
6588
  ref_key: "scrollRef",
6550
6589
  ref: scrollRef,
6551
- class: "fv-messages-scroll"
6590
+ class: "fv-messages-scroll",
6591
+ onScrollPassive: onScroll
6552
6592
  },
6553
6593
  [
6554
6594
  vue.createElementVNode("div", _hoisted_3$2, [
@@ -6623,11 +6663,44 @@ ${fileParts.join("\n")}` });
6623
6663
  }),
6624
6664
  128
6625
6665
  /* KEYED_FRAGMENT */
6626
- ))
6666
+ )),
6667
+ vue.createCommentVNode(" \u6EDA\u5230\u5E95\u90E8\u60AC\u6D6E\u6309\u94AE:\u5728 fv-messages-inner \u5185,\u968F\u5185\u5BB9\u5BBD\u5EA6\u7EA6\u675F\u5C42\u5B9A\u4F4D(\u5BBD\u5C4F\u65F6\u4E0D\u8D34\u89C6\u53E3\u53F3\u7F18);\r\n \u8DDD\u5E95\u8D85\u8FC7 scrollButtonThreshold \u663E\u793A(\u7A7A\u6001\u4E0D\u6E32\u67D3);\r\n scroll-button \u63D2\u69FD\u6574\u4F53\u8986\u76D6\u6309\u94AE,scroll-button-icon \u63D2\u69FD\u4EC5\u8986\u76D6\u56FE\u6807\u5185\u5BB9 "),
6668
+ vue.createVNode(vue.Transition, { name: "fv-messages-back-fade" }, {
6669
+ default: vue.withCtx(() => [
6670
+ vue.renderSlot(_ctx.$slots, "scroll-button", {
6671
+ scrollToBottom,
6672
+ awayFromBottom: isAwayFromBottom.value
6673
+ }, () => [
6674
+ __props.showScrollButton && !isEmpty.value && isAwayFromBottom.value ? (vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElButton), {
6675
+ key: 0,
6676
+ class: "fv-messages-back",
6677
+ circle: "",
6678
+ "aria-label": "\u6EDA\u52A8\u5230\u5E95\u90E8",
6679
+ onClick: _cache[0] || (_cache[0] = ($event) => scrollToBottom())
6680
+ }, {
6681
+ default: vue.withCtx(() => [
6682
+ vue.createVNode(vue.unref(elementPlus.ElIcon), { class: "fv-messages-back-icon" }, {
6683
+ default: vue.withCtx(() => [
6684
+ vue.renderSlot(_ctx.$slots, "scroll-button-icon", {}, () => [
6685
+ vue.createVNode(vue.unref(ElementPlusIconsVue.Bottom))
6686
+ ])
6687
+ ]),
6688
+ _: 3
6689
+ /* FORWARDED */
6690
+ })
6691
+ ]),
6692
+ _: 3
6693
+ /* FORWARDED */
6694
+ })) : vue.createCommentVNode("v-if", true)
6695
+ ])
6696
+ ]),
6697
+ _: 3
6698
+ /* FORWARDED */
6699
+ })
6627
6700
  ])
6628
6701
  ],
6629
- 512
6630
- /* NEED_PATCH */
6702
+ 544
6703
+ /* NEED_HYDRATION, NEED_PATCH */
6631
6704
  )
6632
6705
  ],
6633
6706
  2112
@@ -6912,6 +6985,8 @@ ${fileParts.join("\n")}` });
6912
6985
  title: { type: String, required: false, default: "" },
6913
6986
  showHeader: { type: Boolean, required: false, default: false },
6914
6987
  centerWelcome: { type: Boolean, required: false, default: true },
6988
+ showScrollButton: { type: Boolean, required: false, default: true },
6989
+ scrollButtonThreshold: { type: Number, required: false, default: 100 },
6915
6990
  showUserAvatar: { type: Boolean, required: false, default: true },
6916
6991
  showUserName: { type: Boolean, required: false, default: true },
6917
6992
  showAssistantAvatar: { type: Boolean, required: false, default: true },
@@ -6921,6 +6996,7 @@ ${fileParts.join("\n")}` });
6921
6996
  userName: { type: String, required: false, default: "" },
6922
6997
  assistantName: { type: String, required: false, default: "" },
6923
6998
  placeholder: { type: String, required: false, default: "" },
6999
+ toolStepLabel: { type: Function, required: false, default: void 0 },
6924
7000
  senderShadow: { type: Boolean, required: false, default: true },
6925
7001
  suggestions: { type: Array, required: false, default: () => [] },
6926
7002
  features: { type: Object, required: false, default: () => ({}) },
@@ -6964,6 +7040,7 @@ ${fileParts.join("\n")}` });
6964
7040
  adapter: resolveAdapter,
6965
7041
  models: () => isMultiple.value && selectedModels.value.length ? selectedModels.value : [""],
6966
7042
  initial: { messages: initialTable, currentId: initialId },
7043
+ toolStepLabel: props.toolStepLabel,
6967
7044
  onToolEvent: (ev) => emit("tool-event", ev)
6968
7045
  });
6969
7046
  const { send, stop: stopChat, regenerate: regenerateChat, msgs, isLoading } = chat;
@@ -7183,6 +7260,8 @@ ${fileParts.join("\n")}` });
7183
7260
  nodes: vue.unref(nodeTable),
7184
7261
  name: __props.title,
7185
7262
  suggestions: __props.suggestions,
7263
+ "show-scroll-button": __props.showScrollButton,
7264
+ "scroll-button-threshold": __props.scrollButtonThreshold,
7186
7265
  "show-user-avatar": __props.showUserAvatar,
7187
7266
  "show-user-name": __props.showUserName,
7188
7267
  "show-assistant-avatar": __props.showAssistantAvatar,
@@ -7247,8 +7326,22 @@ ${fileParts.join("\n")}` });
7247
7326
  vue.renderSlot(_ctx.$slots, "empty")
7248
7327
  ]),
7249
7328
  key: "6"
7329
+ } : void 0,
7330
+ _ctx.$slots["scroll-button"] ? {
7331
+ name: "scroll-button",
7332
+ fn: vue.withCtx((scope) => [
7333
+ vue.renderSlot(_ctx.$slots, "scroll-button", vue.normalizeProps(vue.guardReactiveProps(scope)))
7334
+ ]),
7335
+ key: "7"
7336
+ } : void 0,
7337
+ _ctx.$slots["scroll-button-icon"] ? {
7338
+ name: "scroll-button-icon",
7339
+ fn: vue.withCtx(() => [
7340
+ vue.renderSlot(_ctx.$slots, "scroll-button-icon")
7341
+ ]),
7342
+ key: "8"
7250
7343
  } : void 0
7251
- ]), 1032, ["messages", "nodes", "name", "suggestions", "show-user-avatar", "show-user-name", "show-assistant-avatar", "show-assistant-name", "user-avatar", "assistant-avatar", "user-name", "assistant-name"]),
7344
+ ]), 1032, ["messages", "nodes", "name", "suggestions", "show-scroll-button", "scroll-button-threshold", "show-user-avatar", "show-user-name", "show-assistant-avatar", "show-assistant-name", "user-avatar", "assistant-avatar", "user-name", "assistant-name"]),
7252
7345
  __props.features?.artifacts && artifacts.value.length ? (vue.openBlock(), vue.createBlock(_sfc_main$1, {
7253
7346
  key: 0,
7254
7347
  artifacts: artifacts.value,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fv-ui/ai-chat",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "基于 Vue3 + Element Plus 的 AI 对话组件库",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",