diff --git a/change/@acedatacloud-nexior-963da0b3-a7d7-46f5-b9f7-c715520b3be3.json b/change/@acedatacloud-nexior-963da0b3-a7d7-46f5-b9f7-c715520b3be3.json
new file mode 100644
index 00000000..082d9c9c
--- /dev/null
+++ b/change/@acedatacloud-nexior-963da0b3-a7d7-46f5-b9f7-c715520b3be3.json
@@ -0,0 +1,7 @@
+{
+ "type": "minor",
+ "comment": "fix chat restart",
+ "packageName": "@acedatacloud/nexior",
+ "email": "1348977728@qq.com",
+ "dependentChangeType": "patch"
+}
diff --git a/src/components/chat/Message.vue b/src/components/chat/Message.vue
index cc6f8f16..a18d03a2 100644
--- a/src/components/chat/Message.vue
+++ b/src/components/chat/Message.vue
@@ -56,6 +56,14 @@
+
@@ -73,7 +81,8 @@ import { ElAlert, ElButton, ElImage, ElTooltip, ElInput } from 'element-plus';
import MarkdownRenderer from '@/components/common/MarkdownRenderer.vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { IApplication, IChatMessage, IChatMessageState } from '@/models';
-import CopyToClipboard from '../common/CopyToClipboard.vue';
+import CopyToClipboard from '@/components/common/CopyToClipboard.vue';
+import RestartToGenerate from '@/components/common/RestartToGenerate.vue';
import {
ERROR_CODE_API_ERROR,
ERROR_CODE_BAD_REQUEST,
@@ -98,6 +107,7 @@ export default defineComponent({
name: 'Message',
components: {
CopyToClipboard,
+ RestartToGenerate,
AnsweringMark,
MarkdownRenderer,
ElAlert,
@@ -108,6 +118,11 @@ export default defineComponent({
ElInput
},
props: {
+ messages: {
+ type: Array,
+ required: false,
+ default: () => []
+ },
message: {
type: Object as () => IChatMessage,
required: true
@@ -117,7 +132,7 @@ export default defineComponent({
required: true
}
},
- emits: ['stop', 'update:messages', 'edit'],
+ emits: ['stop', 'edit', 'restart'],
data(): IData {
return {
copied: false,
@@ -165,6 +180,10 @@ export default defineComponent({
cancelEdit() {
this.isEditing = false;
},
+ sendRestart() {
+ // Implement the logic to save the edited content
+ this.$emit('restart', this.message);
+ },
sendEdit() {
// Implement the logic to save the edited content
this.isEditing = false;
@@ -312,7 +331,13 @@ export default defineComponent({
}
.operations {
- display: block;
+ display: flex; // Use flexbox for better alignment
+ gap: 10px; // Adjust the gap value as needed
+ margin-left: 5px; // Adjust the value as needed
+ .btn-restart {
+ color: var(--el-text-color-regular);
+ font-size: 14px;
+ }
.btn-copy {
color: var(--el-text-color-regular);
font-size: 14px;
diff --git a/src/components/common/CopyToClipboard.vue b/src/components/common/CopyToClipboard.vue
index 1035fb60..24a98c5a 100644
--- a/src/components/common/CopyToClipboard.vue
+++ b/src/components/common/CopyToClipboard.vue
@@ -1,5 +1,8 @@
-
+
+
+
diff --git a/src/components/common/RestartToGenerate.vue b/src/components/common/RestartToGenerate.vue
new file mode 100644
index 00000000..e04b9e46
--- /dev/null
+++ b/src/components/common/RestartToGenerate.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/i18n/zh-CN/common.json b/src/i18n/zh-CN/common.json
index 735eac7b..cb391d44 100644
--- a/src/i18n/zh-CN/common.json
+++ b/src/i18n/zh-CN/common.json
@@ -3,6 +3,14 @@
"message": "设置",
"description": "按钮文本,用于设置某些内容"
},
+ "button.copy": {
+ "message": "复制该消息",
+ "description": "按钮文本,用于设置某些内容"
+ },
+ "button.restart": {
+ "message": "重新生成",
+ "description": "按钮文本,用于设置某些内容"
+ },
"button.preview": {
"message": "预览",
"description": "按钮文本,用于通过URL打开预览某个文件"
@@ -123,10 +131,6 @@
"message": "查看",
"description": "按钮文本,用于查看某些内容"
},
- "button.copy": {
- "message": "复制",
- "description": "按钮文本,用于复制某些内容"
- },
"button.create": {
"message": "创建",
"description": "按钮文本,用于创建某些内容"
@@ -195,6 +199,10 @@
"message": "已成功复制",
"description": "用于显示内容已成功复制的消息"
},
+ "message.restart": {
+ "message": "重新生成",
+ "description": "用于显示内容已成功复制的消息"
+ },
"message.confirmDelete": {
"message": "确定要删除吗?",
"description": "用于确认用户是否要删除某些内容的消息"
diff --git a/src/pages/chat/Conversation.vue b/src/pages/chat/Conversation.vue
index c549c19f..ac447fa7 100644
--- a/src/pages/chat/Conversation.vue
+++ b/src/pages/chat/Conversation.vue
@@ -21,8 +21,8 @@
:application="application"
class="message"
@update:question="question = $event"
- @update:messages="messages = $event"
@edit="onEdit"
+ @restart="onRestart"
/>
@@ -59,6 +59,7 @@ import { chatOperator } from '@/operators';
import ApplicationStatus from '@/components/application/Status.vue';
export interface IData {
+ drawer: boolean;
question: string;
references: string[];
answering: boolean;
@@ -77,6 +78,7 @@ export default defineComponent({
},
data(): IData {
return {
+ drawer: false,
question: '',
references: [],
answering: false,
@@ -159,6 +161,84 @@ export default defineComponent({
this.question = question;
this.onSubmit();
},
+ async onRestart(targetMessage: IChatMessage) {
+ // 1. Clear the following message
+ const targetIndex = this.messages.findIndex((message) => message === targetMessage);
+ const problem_message = this.messages[targetIndex - 1];
+ if (targetIndex !== -1) {
+ this.messages = this.messages.slice(0, targetIndex - 1);
+ // @ts-ignore
+ this.question = problem_message.content;
+ }
+
+ // 2. Update the messages
+ const token = this.credential?.token;
+ const question = this.question;
+ // reset question and references
+ if (!token || !question) {
+ console.error('no token or endpoint or question');
+ this.messages.push({
+ error: {
+ code: ERROR_CODE_NOT_APPLIED
+ },
+ role: ROLE_ASSISTANT,
+ state: IChatMessageState.FAILED
+ });
+ return;
+ }
+ let conversationId = this.conversationId;
+ chatOperator
+ .updateConversation(
+ {
+ id: this.conversationId,
+ messages: this.messages
+ },
+ {
+ token
+ }
+ )
+ .then(async () => {
+ await this.$store.dispatch('chat/setConversation', {
+ id: conversationId,
+ messages: this.messages
+ });
+ console.debug('finished update conversation', this.messages);
+ this.messages.push({
+ content: this.question,
+ role: ROLE_USER
+ });
+ // 3. Send restart questions
+ console.debug('onRestart', this.question);
+ await this.onFetchAnswer();
+ })
+ .catch((error) => {
+ if (this.messages && this.messages.length > 0) {
+ this.messages[this.messages.length - 1].state = IChatMessageState.FAILED;
+ }
+ console.error(error);
+ if (axios.isCancel(error)) {
+ this.messages[this.messages.length - 1].error = {
+ code: ERROR_CODE_CANCELED
+ };
+ } else if (error?.response?.data) {
+ let data = error?.response?.data;
+ if (isJSONString(data)) {
+ data = JSON.parse(data);
+ }
+ console.debug('error', data);
+ if (this.messages && this.messages.length > 0) {
+ this.messages[this.messages.length - 1].error = data.error;
+ }
+ } else {
+ if (this.messages && this.messages.length > 0) {
+ this.messages[this.messages.length - 1].error = {
+ code: ERROR_CODE_UNKNOWN
+ };
+ }
+ }
+ this.answering = false;
+ });
+ },
async onEdit(targetMessage: IChatMessage, questionValue: string) {
// 1. Clear the following message
const targetIndex = this.messages.findIndex((message) => message === targetMessage);
@@ -342,6 +422,7 @@ export default defineComponent({
id: conversationId,
messages: this.messages
});
+ console.log('messages', JSON.stringify(this.messages));
this.answering = false;
if (!this.conversationId) {
await this.$router.push({
@@ -395,6 +476,17 @@ export default defineComponent({
left: 10px;
top: 10px;
}
+.setting {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ margin-bottom: 10px;
+}
+@media (max-width: 767px) {
+ .setting {
+ display: none;
+ }
+}
.dialogue {
flex: 1;
@@ -409,6 +501,7 @@ export default defineComponent({
}
}
}
+
.bottom {
width: 100%;
}
diff --git a/src/plugins/font-awesome.ts b/src/plugins/font-awesome.ts
index b7d56807..9e71213f 100644
--- a/src/plugins/font-awesome.ts
+++ b/src/plugins/font-awesome.ts
@@ -10,6 +10,7 @@ import {
} from '@fortawesome/free-regular-svg-icons';
import { faDiscord as faBrandsDiscord, faWeixin as faBrandsWeixin } from '@fortawesome/free-brands-svg-icons';
import {
+ faSync as faSolidSync,
faDownload as faSolidDownload,
faMusic as faSolidMusic,
faLanguage as faSolidLanguage,
@@ -73,6 +74,7 @@ import {
faWandMagic as faSolidWandMagic,
faAngleDown as faSolidAngleDown
} from '@fortawesome/free-solid-svg-icons';
+library.add(faSolidSync);
library.add(faSolidMusic);
library.add(faRegularCopy);
library.add(faRegularMessage);