XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Add remove messages from history Improve hidding regenerated messages

43cb4e61
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

2 个文件 +95 -23
Modified g4f/gui/client/css/style.css +21 -1
@@ -316,13 +316,33 @@ body {
316 316 z-index: 1000;
317 317 }
318 318
319 .message .assistant i {
319 .message .assistant .fa-phone-arrow-up-right,
320 .message .assistant .fa-phone-arrow-down-left {
320 321 position: absolute;
321 322 bottom: -6px;
322 323 right: -6px;
323 324 z-index: 1000;
324 325 }
325 326
327 .message .assistant .fa-xmark,
328 .message .user .fa-xmark {
329 position: absolute;
330 top: -2px;
331 left: 0px;
332 z-index: 1000;
333 display: none;
334 cursor: pointer;
335 }
336
337 .message .user .fa-xmark {
338 color: var(--colour-1);
339 }
340
341 .message .assistant:hover .fa-xmark,
342 .message .user:hover .fa-xmark {
343 display: block;
344 }
345
326 346 .new_convo {
327 347 padding: 8px 12px;
328 348 display: flex;
Modified g4f/gui/client/js/chat.v1.js +74 -22
@@ -46,6 +46,22 @@ const highlight = (container) => {
46 46 );
47 47 }
48 48
49 const register_remove_message = async () => {
50 document.querySelectorAll(".message .fa-xmark").forEach(async (el) => {
51 if (!("click" in el.dataset)) {
52 el.dataset.click = "true";
53 el.addEventListener("click", async () => {
54 if (prompt_lock) {
55 return;
56 }
57 const message_el = el.parentElement.parentElement;
58 await remove_message(window.conversation_id, message_el.dataset.index);
59 await load_conversation(window.conversation_id);
60 })
61 }
62 });
63 }
64
49 65 const delete_conversations = async () => {
50 66 localStorage.clear();
51 67 await new_conversation();
@@ -58,13 +74,14 @@ const handle_ask = async () => {
58 74 message = message_input.value
59 75 if (message.length > 0) {
60 76 message_input.value = '';
77 prompt_lock = true;
61 78 await add_conversation(window.conversation_id, message);
62 79 if ("text" in fileInput.dataset) {
63 80 message += '\n```' + fileInput.dataset.type + '\n';
64 81 message += fileInput.dataset.text;
65 82 message += '\n```'
66 83 }
67 await add_message(window.conversation_id, "user", message);
84 let message_index = await add_message(window.conversation_id, "user", message);
68 85 window.token = message_id();
69 86
70 87 if (imageInput.dataset.src) URL.revokeObjectURL(imageInput.dataset.src);
@@ -73,9 +90,10 @@ const handle_ask = async () => {
73 90 else delete imageInput.dataset.src
74 91
75 92 message_box.innerHTML += `
76 <div class="message">
93 <div class="message" data-index="${message_index}">
77 94 <div class="user">
78 95 ${user_image}
96 <i class="fa-solid fa-xmark"></i>
79 97 <i class="fa-regular fa-phone-arrow-up-right"></i>
80 98 </div>
81 99 <div class="content" id="user_${token}">
@@ -87,6 +105,7 @@ const handle_ask = async () => {
87 105 </div>
88 106 </div>
89 107 `;
108 await register_remove_message();
90 109 highlight(message_box);
91 110 await ask_gpt();
92 111 }
@@ -105,18 +124,24 @@ const ask_gpt = async () => {
105 124 regenerate.classList.add(`regenerate-hidden`);
106 125 messages = await get_messages(window.conversation_id);
107 126
108 // Remove generated images from history
127 // Remove history, if it is selected
128 if (document.getElementById('history')?.checked) {
129 messages = [messages[messages.length-1]]
130 }
131
132 new_messages = [];
109 133 for (i in messages) {
110 messages[i]["content"] = messages[i]["content"].replaceAll(
134 new_message = messages[i];
135 // Remove generated images from history
136 new_message["content"] = new_message["content"].replaceAll(
111 137 /<!-- generated images start -->[\s\S]+<!-- generated images end -->/gm,
112 138 ""
113 139 )
114 delete messages[i]["provider"];
115 }
116
117 // Remove history, if it is selected
118 if (document.getElementById('history')?.checked) {
119 messages = [messages[messages.length-1]]
140 delete new_message["provider"];
141 // Remove regenerated messages
142 if (!new_message.regenerate) {
143 new_messages.push(new_message)
144 }
120 145 }
121 146
122 147 window.scrollTo(0, 0);
@@ -125,7 +150,6 @@ const ask_gpt = async () => {
125 150 jailbreak = document.getElementById("jailbreak");
126 151 provider = document.getElementById("provider");
127 152 model = document.getElementById("model");
128 prompt_lock = true;
129 153 window.text = '';
130 154
131 155 stop_generating.classList.remove(`stop_generating-hidden`);
@@ -136,9 +160,11 @@ const ask_gpt = async () => {
136 160 window.scrollTo(0, 0);
137 161
138 162 message_box.innerHTML += `
139 <div class="message">
163 <div class="message" data-index="${new_messages.length}">
140 164 <div class="assistant">
141 ${gpt_image} <i class="fa-regular fa-phone-arrow-down-left"></i>
165 ${gpt_image}
166 <i class="fa-solid fa-xmark"></i>
167 <i class="fa-regular fa-phone-arrow-down-left"></i>
142 168 </div>
143 169 <div class="content" id="gpt_${window.token}">
144 170 <div class="provider"></div>
@@ -160,7 +186,7 @@ const ask_gpt = async () => {
160 186 web_search: document.getElementById(`switch`).checked,
161 187 provider: provider.options[provider.selectedIndex].value,
162 188 patch_provider: document.getElementById('patch').checked,
163 messages: messages
189 messages: new_messages
164 190 });
165 191 const headers = {
166 192 accept: 'text/event-stream'
@@ -185,7 +211,6 @@ const ask_gpt = async () => {
185 211 window.scrollTo(0, 0);
186 212
187 213 const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
188
189 214 error = provider = null;
190 215 while (true) {
191 216 const { value, done } = await reader.read();
@@ -252,9 +277,12 @@ const ask_gpt = async () => {
252 277 }
253 278 let cursorDiv = document.getElementById(`cursor`);
254 279 if (cursorDiv) cursorDiv.parentNode.removeChild(cursorDiv);
255 add_message(window.conversation_id, "assistant", text, provider);
280 if (text) {
281 add_message(window.conversation_id, "assistant", text, provider);
282 }
256 283 message_box.scrollTop = message_box.scrollHeight;
257 284 await remove_cancel_button();
285 await register_remove_message();
258 286 prompt_lock = false;
259 287 window.scrollTo(0, 0);
260 288 await load_conversations(20, 0);
@@ -342,7 +370,8 @@ const load_conversation = async (conversation_id) => {
342 370 let messages = await get_messages(conversation_id);
343 371
344 372 let elements = "";
345 for (item of messages) {
373 for (i in messages) {
374 let item = messages[i];
346 375 let provider = item.provider ? `
347 376 <div class="provider">
348 377 <a href="${item.provider.url}" target="_blank">${item.provider.name}</a>
@@ -350,9 +379,10 @@ const load_conversation = async (conversation_id) => {
350 379 </div>
351 380 ` : "";
352 381 elements += `
353 <div class="message">
382 <div class="message" data-index="${i}">
354 383 <div class=${item.role == "assistant" ? "assistant" : "user"}>
355 384 ${item.role == "assistant" ? gpt_image : user_image}
385 <i class="fa-solid fa-xmark"></i>
356 386 ${item.role == "assistant"
357 387 ? `<i class="fa-regular fa-phone-arrow-down-left"></i>`
358 388 : `<i class="fa-regular fa-phone-arrow-up-right"></i>`
@@ -367,6 +397,7 @@ const load_conversation = async (conversation_id) => {
367 397 }
368 398 message_box.innerHTML = elements;
369 399
400 await register_remove_message();
370 401 highlight(message_box);
371 402
372 403 message_box.scrollTo({ top: message_box.scrollHeight, behavior: "smooth" });
@@ -409,11 +440,30 @@ const add_conversation = async (conversation_id, content) => {
409 440 history.pushState({}, null, `/chat/${conversation_id}`);
410 441 };
411 442
412 const remove_last_message = async (conversation_id) => {
443 const hide_last_message = async (conversation_id) => {
413 444 const conversation = await get_conversation(conversation_id)
445 const last_message = conversation.items.pop();
446 last_message["regenerate"] = true;
447 conversation.items.push(last_message);
414 448
415 conversation.items.pop();
449 localStorage.setItem(
450 `conversation:${conversation_id}`,
451 JSON.stringify(conversation)
452 );
453 };
416 454
455 const remove_message = async (conversation_id, index) => {
456 const conversation = await get_conversation(conversation_id);
457 let new_items = [];
458 for (i in conversation.items) {
459 if (i == index - 1) {
460 delete conversation.items[i]["regenerate"];
461 }
462 if (i != index) {
463 new_items.push(conversation.items[i])
464 }
465 }
466 conversation.items = new_items;
417 467 localStorage.setItem(
418 468 `conversation:${conversation_id}`,
419 469 JSON.stringify(conversation)
@@ -433,6 +483,8 @@ const add_message = async (conversation_id, role, content, provider) => {
433 483 `conversation:${conversation_id}`,
434 484 JSON.stringify(conversation)
435 485 );
486
487 return conversation.items.length - 1;
436 488 };
437 489
438 490 const load_conversations = async (limit, offset, loader) => {
@@ -468,7 +520,8 @@ document.getElementById(`cancelButton`).addEventListener(`click`, async () => {
468 520 });
469 521
470 522 document.getElementById(`regenerateButton`).addEventListener(`click`, async () => {
471 await remove_last_message(window.conversation_id);
523 prompt_lock = true;
524 await hide_last_message(window.conversation_id);
472 525 window.token = message_id();
473 526 await ask_gpt();
474 527 });
@@ -591,7 +644,6 @@ colorThemes.forEach((themeOption) => {
591 644 });
592 645 });
593 646
594
595 647 window.onload = async () => {
596 648 setTheme();
597 649