维护 Agent 对话
This commit is contained in:
parent
cde6b98336
commit
58df6a599e
@ -79,20 +79,11 @@
|
|||||||
v-for="message in conv.messages"
|
v-for="message in conv.messages"
|
||||||
:message="message"
|
:message="message"
|
||||||
:key="message.id"
|
:key="message.id"
|
||||||
:role="message.role"
|
|
||||||
:content="message.text"
|
|
||||||
:content-html="message.text.length > 0 ? renderMarkdown(message) : ''"
|
|
||||||
:reasoning-content="message.reasoning_content"
|
|
||||||
:reasoning-header="message.status=='reasoning' ? '正在思考...' : '推理过程'"
|
|
||||||
:status="message.status"
|
|
||||||
:is-processing="isStreaming"
|
:is-processing="isStreaming"
|
||||||
:error-message="message.message"
|
:show-refs="true"
|
||||||
@retry="retryMessage(message.id)"
|
@retry="retryMessage(message.id)"
|
||||||
@retryStoppedMessage="retryStoppedMessage(message.id)"
|
@retryStoppedMessage="retryStoppedMessage(message.id)"
|
||||||
>
|
>
|
||||||
<template #refs v-if="message.role=='received' && message.status=='finished'">
|
|
||||||
<RefsComponent :message="message" :conv="conv" @retry="retryMessage(message.id)" />
|
|
||||||
</template>
|
|
||||||
</MessageComponent>
|
</MessageComponent>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom">
|
<div class="bottom">
|
||||||
@ -178,13 +169,8 @@ import {
|
|||||||
CopyOutlined
|
CopyOutlined
|
||||||
} from '@ant-design/icons-vue'
|
} from '@ant-design/icons-vue'
|
||||||
import { onClickOutside } from '@vueuse/core'
|
import { onClickOutside } from '@vueuse/core'
|
||||||
import { Marked } from 'marked';
|
|
||||||
import { markedHighlight } from 'marked-highlight';
|
|
||||||
import { useConfigStore } from '@/stores/config'
|
import { useConfigStore } from '@/stores/config'
|
||||||
import { message } from 'ant-design-vue'
|
import { message } from 'ant-design-vue'
|
||||||
import RefsComponent from '@/components/RefsComponent.vue'
|
|
||||||
import hljs from 'highlight.js';
|
|
||||||
import 'highlight.js/styles/github.css';
|
|
||||||
import MessageInputComponent from '@/components/MessageInputComponent.vue'
|
import MessageInputComponent from '@/components/MessageInputComponent.vue'
|
||||||
import MessageComponent from '@/components/MessageComponent.vue'
|
import MessageComponent from '@/components/MessageComponent.vue'
|
||||||
|
|
||||||
@ -232,39 +218,18 @@ const meta = reactive(JSON.parse(localStorage.getItem('meta')) || {
|
|||||||
wideScreen: false,
|
wideScreen: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const marked = new Marked(
|
|
||||||
{
|
|
||||||
gfm: true,
|
|
||||||
breaks: true,
|
|
||||||
tables: true,
|
|
||||||
},
|
|
||||||
markedHighlight({
|
|
||||||
langPrefix: 'hljs language-',
|
|
||||||
highlight(code) {
|
|
||||||
return hljs.highlightAuto(code).value;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const consoleMsg = (msg) => console.log(msg)
|
const consoleMsg = (msg) => console.log(msg)
|
||||||
onClickOutside(panel, () => setTimeout(() => opts.showPanel = false, 30))
|
onClickOutside(panel, () => setTimeout(() => opts.showPanel = false, 30))
|
||||||
onClickOutside(modelCard, () => setTimeout(() => opts.showModelCard = false, 30))
|
onClickOutside(modelCard, () => setTimeout(() => opts.showModelCard = false, 30))
|
||||||
|
|
||||||
const renderMarkdown = (msg) => {
|
|
||||||
if (msg.status === 'loading') {
|
|
||||||
return marked.parse(msg.text + '🟢')
|
|
||||||
} else {
|
|
||||||
return marked.parse(msg.text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从 message 中获取 history 信息,每个消息都是 {role, content} 的格式
|
// 从 message 中获取 history 信息,每个消息都是 {role, content} 的格式
|
||||||
const getHistory = () => {
|
const getHistory = () => {
|
||||||
const history = conv.value.messages.map((msg) => {
|
const history = conv.value.messages.map((msg) => {
|
||||||
if (msg.text) {
|
if (msg.content) {
|
||||||
return {
|
return {
|
||||||
role: msg.role === 'sent' ? 'user' : 'assistant',
|
role: msg.role === 'sent' ? 'user' : 'assistant',
|
||||||
content: msg.text
|
content: msg.content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).reduce((acc, cur) => {
|
}).reduce((acc, cur) => {
|
||||||
@ -309,15 +274,15 @@ const handleKeyDown = (e) => {
|
|||||||
const renameTitle = () => {
|
const renameTitle = () => {
|
||||||
if (meta.summary_title) {
|
if (meta.summary_title) {
|
||||||
const prompt = '请用一个很短的句子关于下面的对话内容的主题起一个名字,不要带标点符号:'
|
const prompt = '请用一个很短的句子关于下面的对话内容的主题起一个名字,不要带标点符号:'
|
||||||
const firstUserMessage = conv.value.messages[0].text
|
const firstUserMessage = conv.value.messages[0].content
|
||||||
const firstAiMessage = conv.value.messages[1].text
|
const firstAiMessage = conv.value.messages[1].content
|
||||||
const context = `${prompt}\n\n问题: ${firstUserMessage}\n\n回复: ${firstAiMessage},主题是(一句话):`
|
const context = `${prompt}\n\n问题: ${firstUserMessage}\n\n回复: ${firstAiMessage},主题是(一句话):`
|
||||||
simpleCall(context).then((data) => {
|
simpleCall(context).then((data) => {
|
||||||
const response = data.response.split(":")[0].replace(/^["'"']/g, '').replace(/["'"']$/g, '')
|
const response = data.response.split(":")[0].replace(/^["'"']/g, '').replace(/["'"']$/g, '')
|
||||||
emit('rename-title', response)
|
emit('rename-title', response)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
emit('rename-title', conv.value.messages[0].text)
|
emit('rename-title', conv.value.messages[0].content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,16 +318,16 @@ const appendUserMessage = (msg) => {
|
|||||||
conv.value.messages.push({
|
conv.value.messages.push({
|
||||||
id: generateRandomHash(16),
|
id: generateRandomHash(16),
|
||||||
role: 'sent',
|
role: 'sent',
|
||||||
text: msg
|
content: msg
|
||||||
})
|
})
|
||||||
scrollToBottom()
|
scrollToBottom()
|
||||||
}
|
}
|
||||||
|
|
||||||
const appendAiMessage = (text, refs=null) => {
|
const appendAiMessage = (content, refs=null) => {
|
||||||
conv.value.messages.push({
|
conv.value.messages.push({
|
||||||
id: generateRandomHash(16),
|
id: generateRandomHash(16),
|
||||||
role: 'received',
|
role: 'received',
|
||||||
text: text,
|
content: content,
|
||||||
reasoning_content: '',
|
reasoning_content: '',
|
||||||
refs,
|
refs,
|
||||||
status: "init",
|
status: "init",
|
||||||
@ -377,8 +342,8 @@ const updateMessage = (info) => {
|
|||||||
if (msg) {
|
if (msg) {
|
||||||
try {
|
try {
|
||||||
// 只有在 text 不为空时更新
|
// 只有在 text 不为空时更新
|
||||||
if (info.text !== null && info.text !== undefined && info.text !== '') {
|
if (info.content !== null && info.content !== undefined && info.content !== '') {
|
||||||
msg.text += info.text;
|
msg.content += info.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.reasoning_content !== null && info.reasoning_content !== undefined && info.reasoning_content !== '') {
|
if (info.reasoning_content !== null && info.reasoning_content !== undefined && info.reasoning_content !== '') {
|
||||||
@ -415,7 +380,7 @@ const updateMessage = (info) => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating message:', error);
|
console.error('Error updating message:', error);
|
||||||
msg.status = 'error';
|
msg.status = 'error';
|
||||||
msg.text = '消息更新失败';
|
msg.content = '消息更新失败';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('Message not found:', info.id);
|
console.error('Message not found:', info.id);
|
||||||
@ -512,13 +477,13 @@ const fetchChatResponse = (user_input, cur_res_id) => {
|
|||||||
const data = JSON.parse(line);
|
const data = JSON.parse(line);
|
||||||
updateMessage({
|
updateMessage({
|
||||||
id: cur_res_id,
|
id: cur_res_id,
|
||||||
text: data.response,
|
content: data.response,
|
||||||
reasoning_content: data.reasoning_content,
|
reasoning_content: data.reasoning_content,
|
||||||
status: data.status,
|
status: data.status,
|
||||||
meta: data.meta,
|
meta: data.meta,
|
||||||
...data,
|
...data,
|
||||||
});
|
});
|
||||||
// console.log("Last message", conv.value.messages[conv.value.messages.length - 1].text)
|
// console.log("Last message", conv.value.messages[conv.value.messages.length - 1].content)
|
||||||
// console.log("Last message", conv.value.messages[conv.value.messages.length - 1].status)
|
// console.log("Last message", conv.value.messages[conv.value.messages.length - 1].status)
|
||||||
|
|
||||||
if (data.history) {
|
if (data.history) {
|
||||||
@ -588,7 +553,7 @@ const retryMessage = (id) => {
|
|||||||
const index = conv.value.messages.findIndex(msg => msg.id === id);
|
const index = conv.value.messages.findIndex(msg => msg.id === id);
|
||||||
const pastMessage = conv.value.messages[index-1]
|
const pastMessage = conv.value.messages[index-1]
|
||||||
console.log("retryMessage", id, pastMessage)
|
console.log("retryMessage", id, pastMessage)
|
||||||
conv.value.inputText = pastMessage.text
|
conv.value.inputText = pastMessage.content
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
conv.value.messages = conv.value.messages.slice(0, index-1);
|
conv.value.messages = conv.value.messages.slice(0, index-1);
|
||||||
}
|
}
|
||||||
@ -606,7 +571,7 @@ onMounted(() => {
|
|||||||
// 检查现有消息中是否有内容为空的情况
|
// 检查现有消息中是否有内容为空的情况
|
||||||
if (conv.value.messages && conv.value.messages.length > 0) {
|
if (conv.value.messages && conv.value.messages.length > 0) {
|
||||||
conv.value.messages.forEach(msg => {
|
conv.value.messages.forEach(msg => {
|
||||||
if (msg.role === 'received' && (!msg.text || msg.text.trim() === '')) {
|
if (msg.role === 'received' && (!msg.content || msg.content.trim() === '')) {
|
||||||
msg.status = 'error';
|
msg.status = 'error';
|
||||||
msg.message = '内容加载失败';
|
msg.message = '内容加载失败';
|
||||||
}
|
}
|
||||||
@ -669,7 +634,7 @@ const retryStoppedMessage = (id) => {
|
|||||||
if (messageIndex > 0) {
|
if (messageIndex > 0) {
|
||||||
const userMessage = conv.value.messages[messageIndex - 1];
|
const userMessage = conv.value.messages[messageIndex - 1];
|
||||||
if (userMessage && userMessage.role === 'sent') {
|
if (userMessage && userMessage.role === 'sent') {
|
||||||
conv.value.inputText = userMessage.text;
|
conv.value.inputText = userMessage.content;
|
||||||
// 删除被停止的消息,以及所有后面的消息
|
// 删除被停止的消息,以及所有后面的消息
|
||||||
conv.value.messages = conv.value.messages.slice(0, messageIndex-1);
|
conv.value.messages = conv.value.messages.slice(0, messageIndex-1);
|
||||||
// sendMessage();
|
// sendMessage();
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="message-box" :class="[role, customClasses]">
|
<div class="message-box" :class="[message.role, customClasses]">
|
||||||
<!-- 用户消息 -->
|
<!-- 用户消息 -->
|
||||||
<p v-if="role === 'user' || role === 'sent'" class="message-text">{{ content }}</p>
|
<p v-if="message.role === 'user' || message.role === 'sent'" class="message-text">{{ message.content }}</p>
|
||||||
|
|
||||||
<!-- 助手消息 -->
|
<!-- 助手消息 -->
|
||||||
<div v-else-if="role === 'assistant' || role === 'received'" class="assistant-message">
|
<div v-else-if="message.role === 'assistant' || message.role === 'received'" class="assistant-message">
|
||||||
<!-- 推理过程 (ChatComponent特有) -->
|
<!-- 推理过程 (ChatComponent特有) -->
|
||||||
<div v-if="reasoningContent" class="reasoning-box">
|
<div v-if="message.reasoning_content" class="reasoning-box">
|
||||||
<a-collapse v-model:activeKey="reasoningActiveKey" :bordered="false">
|
<a-collapse v-model:activeKey="reasoningActiveKey" :bordered="false">
|
||||||
<template #expandIcon="{ isActive }">
|
<template #expandIcon="{ isActive }">
|
||||||
<caret-right-outlined :rotate="isActive ? 90 : 0" />
|
<caret-right-outlined :rotate="isActive ? 90 : 0" />
|
||||||
</template>
|
</template>
|
||||||
<a-collapse-panel key="show" :header="reasoningHeader" class="reasoning-header">
|
<a-collapse-panel key="show" :header="message.status=='reasoning' ? '正在思考...' : '推理过程'" class="reasoning-header">
|
||||||
<p class="reasoning-content">{{ reasoningContent }}</p>
|
<p class="reasoning-content">{{ message.reasoning_content }}</p>
|
||||||
</a-collapse-panel>
|
</a-collapse-panel>
|
||||||
</a-collapse>
|
</a-collapse>
|
||||||
</div>
|
</div>
|
||||||
@ -25,21 +25,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 检索中状态 (ChatComponent特有) -->
|
<!-- 检索中状态 (ChatComponent特有) -->
|
||||||
<div v-else-if="status === 'searching' && isProcessing" class="searching-msg">
|
<div v-else-if="message.status === 'searching' && isProcessing" class="searching-msg">
|
||||||
<i>正在检索……</i>
|
<i>正在检索……</i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 生成中状态 (ChatComponent特有) -->
|
<!-- 生成中状态 (ChatComponent特有) -->
|
||||||
<div v-else-if="status === 'generating' && isProcessing" class="searching-msg">
|
<div v-else-if="message.status === 'generating' && isProcessing" class="searching-msg">
|
||||||
<i>正在生成……</i>
|
<i>正在生成……</i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="status === 'error'" class="err-msg" @click="$emit('retry')">
|
<div v-else-if="message.status === 'error'" class="err-msg" @click="$emit('retry')">
|
||||||
请求错误,请重试。{{ errorMessage }}
|
请求错误,请重试。{{ message.message }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 消息内容 -->
|
<!-- 消息内容 -->
|
||||||
<div v-else-if="contentHtml" v-html="contentHtml" class="message-md"></div>
|
<div v-else-if="message.content" v-html="renderMarkdown(message)" class="message-md"></div>
|
||||||
|
|
||||||
<div v-if="message.isStoppedByUser" class="retry-hint">
|
<div v-if="message.isStoppedByUser" class="retry-hint">
|
||||||
你停止生成了本次回答
|
你停止生成了本次回答
|
||||||
@ -49,8 +49,9 @@
|
|||||||
<!-- 工具调用 (AgentView特有) -->
|
<!-- 工具调用 (AgentView特有) -->
|
||||||
<slot name="tool-calls"></slot>
|
<slot name="tool-calls"></slot>
|
||||||
|
|
||||||
<!-- 引用组件 (ChatComponent特有) -->
|
<div v-if="(message.role=='received' || message.role=='assistant') && message.status=='finished' && showRefs">
|
||||||
<slot name="refs"></slot>
|
<RefsComponent :message="message" @retry="emit('retry')" />
|
||||||
|
</div>
|
||||||
<!-- 错误消息 -->
|
<!-- 错误消息 -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -62,6 +63,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { CaretRightOutlined } from '@ant-design/icons-vue';
|
import { CaretRightOutlined } from '@ant-design/icons-vue';
|
||||||
|
import RefsComponent from '@/components/RefsComponent.vue'
|
||||||
|
|
||||||
|
import { Marked } from 'marked';
|
||||||
|
import { markedHighlight } from 'marked-highlight';
|
||||||
|
import hljs from 'highlight.js';
|
||||||
|
import 'highlight.js/styles/github.css';
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
// 消息角色:'user'|'assistant'|'sent'|'received'
|
// 消息角色:'user'|'assistant'|'sent'|'received'
|
||||||
@ -69,49 +77,25 @@ const props = defineProps({
|
|||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
role: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
// 消息内容
|
|
||||||
content: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 已渲染的HTML内容
|
// 已渲染的HTML内容
|
||||||
contentHtml: {
|
contentHtml: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
// 推理内容 (ChatComponent使用)
|
|
||||||
reasoningContent: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 消息状态
|
|
||||||
status: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 是否正在处理中
|
// 是否正在处理中
|
||||||
isProcessing: {
|
isProcessing: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
// 错误信息
|
|
||||||
errorMessage: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
// 自定义类
|
// 自定义类
|
||||||
customClasses: {
|
customClasses: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
},
|
},
|
||||||
// 推理框标题
|
// 是否显示推理过程
|
||||||
reasoningHeader: {
|
showRefs: {
|
||||||
type: String,
|
type: Boolean,
|
||||||
default: '推理过程'
|
default: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -128,10 +112,36 @@ const emit = defineEmits(['retry', 'retryStoppedMessage']);
|
|||||||
// 推理面板展开状态
|
// 推理面板展开状态
|
||||||
const reasoningActiveKey = ref(['show']);
|
const reasoningActiveKey = ref(['show']);
|
||||||
|
|
||||||
|
|
||||||
|
const renderMarkdown = (msg) => {
|
||||||
|
if (!msg.content) return '';
|
||||||
|
|
||||||
|
if (msg.status === 'loading') {
|
||||||
|
return marked.parse(msg.content + '🟢')
|
||||||
|
} else {
|
||||||
|
return marked.parse(msg.content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const marked = new Marked(
|
||||||
|
{
|
||||||
|
gfm: true,
|
||||||
|
breaks: true,
|
||||||
|
tables: true,
|
||||||
|
},
|
||||||
|
markedHighlight({
|
||||||
|
langPrefix: 'hljs language-',
|
||||||
|
highlight(code) {
|
||||||
|
return hljs.highlightAuto(code).value;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
// 计算属性:内容为空且正在加载
|
// 计算属性:内容为空且正在加载
|
||||||
const isEmptyAndLoading = computed(() => {
|
const isEmptyAndLoading = computed(() => {
|
||||||
const isEmpty = !props.content || props.content.length === 0;
|
const isEmpty = !props.message.content || props.message.content.length === 0;
|
||||||
const isLoading = props.status === 'init'
|
const isLoading = props.message.status === 'init'
|
||||||
return isEmpty && isLoading;
|
return isEmpty && isLoading;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
<div class="tags">
|
<div class="tags">
|
||||||
<!-- <span class="item btn" @click="likeThisResponse(msg)"><LikeOutlined /></span> -->
|
<!-- <span class="item btn" @click="likeThisResponse(msg)"><LikeOutlined /></span> -->
|
||||||
<!-- <span class="item btn" @click="dislikeThisResponse(msg)"><DislikeOutlined /></span> -->
|
<!-- <span class="item btn" @click="dislikeThisResponse(msg)"><DislikeOutlined /></span> -->
|
||||||
<span class="item"><BulbOutlined /> {{ msg.meta.server_model_name }}</span>
|
<span v-if="msg.meta?.server_model_name" class="item"><BulbOutlined /> {{ msg.meta.server_model_name }}</span>
|
||||||
<span class="item btn" @click="copyText(msg.text)" title="复制"><CopyOutlined /></span>
|
<span class="item btn" @click="copyText(msg.content)" title="复制"><CopyOutlined /></span>
|
||||||
<span class="item btn" @click="regenerateMessage()" title="重新生成"><ReloadOutlined /></span>
|
<span class="item btn" @click="regenerateMessage()" title="重新生成"><ReloadOutlined /></span>
|
||||||
<span
|
<span
|
||||||
class="item btn"
|
class="item btn"
|
||||||
@ -120,11 +120,9 @@ import GraphContainer from './GraphContainer.vue' // 导入 GraphContainer 组
|
|||||||
const emit = defineEmits(['retry']);
|
const emit = defineEmits(['retry']);
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
message: Object,
|
message: Object,
|
||||||
conv: Object,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const msg = ref(props.message)
|
const msg = ref(props.message)
|
||||||
const conv = ref(props.conv)
|
|
||||||
|
|
||||||
// 使用 useClipboard 实现复制功能
|
// 使用 useClipboard 实现复制功能
|
||||||
const { copy, isSupported } = useClipboard()
|
const { copy, isSupported } = useClipboard()
|
||||||
@ -166,7 +164,7 @@ const toggleDrawer = (filename) => {
|
|||||||
openDetail[filename] = !openDetail[filename]
|
openDetail[filename] = !openDetail[filename]
|
||||||
}
|
}
|
||||||
|
|
||||||
const showRefs = computed(() => msg.value.role=='received' && msg.value.status=='finished')
|
const showRefs = computed(() => (msg.value.role=='received' || msg.value.role=='assistant') && msg.value.status=='finished')
|
||||||
|
|
||||||
const subGraphVisible = ref(false)
|
const subGraphVisible = ref(false)
|
||||||
const subGraphData = ref(null)
|
const subGraphData = ref(null)
|
||||||
|
|||||||
@ -38,13 +38,9 @@
|
|||||||
<div class="chat-box" ref="messagesContainer" :class="{ 'is-debug': options.debug_mode }">
|
<div class="chat-box" ref="messagesContainer" :class="{ 'is-debug': options.debug_mode }">
|
||||||
<MessageComponent
|
<MessageComponent
|
||||||
v-for="(message, index) in messages"
|
v-for="(message, index) in messages"
|
||||||
|
:message="message"
|
||||||
:key="index"
|
:key="index"
|
||||||
:role="message.role"
|
|
||||||
:content="message.content"
|
|
||||||
:content-html="message.content ? renderMarkdown(message.content) : ''"
|
|
||||||
:status="message.status"
|
|
||||||
:is-processing="isProcessing"
|
:is-processing="isProcessing"
|
||||||
:error-message="message.message"
|
|
||||||
@retry="retryMessage(index)"
|
@retry="retryMessage(index)"
|
||||||
>
|
>
|
||||||
<div v-if="options.debug_mode" class="status-info">{{ message }}</div>
|
<div v-if="options.debug_mode" class="status-info">{{ message }}</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user