@fivetu53/soul-chat 1.1.2 → 1.1.3
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/bin/api.js +13 -0
- package/bin/index.js +73 -57
- package/package.json +1 -1
package/bin/api.js
CHANGED
|
@@ -237,6 +237,19 @@ export async function deleteLastMessages(conversationId) {
|
|
|
237
237
|
return data;
|
|
238
238
|
}
|
|
239
239
|
|
|
240
|
+
export async function regenerateMessage(conversationId) {
|
|
241
|
+
const response = await request(`/api/chat/conversations/${conversationId}/regenerate`, {
|
|
242
|
+
method: 'POST'
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
if (!response.ok) {
|
|
246
|
+
const data = await response.json();
|
|
247
|
+
throw new Error(data.error);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return response;
|
|
251
|
+
}
|
|
252
|
+
|
|
240
253
|
// Memory APIs
|
|
241
254
|
export async function getMemories(characterId) {
|
|
242
255
|
const response = await request(`/api/memories/${characterId}`);
|
package/bin/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { loadConfig, saveConfig, getConfigPath } from './config.js';
|
|
|
10
10
|
import { checkAuth, showAuthScreen } from './auth.js';
|
|
11
11
|
import {
|
|
12
12
|
isLoggedIn, getCurrentUser, logout, updateProfile,
|
|
13
|
-
sendMessage, getCharacters, createCharacter, getConversations, getMessages, clearConversation, deleteLastMessages, getMemories, pinMemory, deleteMemory
|
|
13
|
+
sendMessage, getCharacters, createCharacter, getConversations, getMessages, clearConversation, deleteLastMessages, regenerateMessage, getMemories, pinMemory, deleteMemory
|
|
14
14
|
} from './api.js';
|
|
15
15
|
|
|
16
16
|
// Setup marked with terminal renderer
|
|
@@ -553,66 +553,82 @@ async function showChat() {
|
|
|
553
553
|
|
|
554
554
|
if (input === '/regen') {
|
|
555
555
|
// 重新生成最后一条回复
|
|
556
|
-
if (
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
556
|
+
if (!currentConversationId) {
|
|
557
|
+
console.log(c('yellow', ' 没有可重新生成的对话'));
|
|
558
|
+
await sleep(1000);
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// 找到最后一条 AI 回复的索引
|
|
563
|
+
let lastBotIdx = -1;
|
|
564
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
565
|
+
if (messages[i].role === 'bot') {
|
|
566
|
+
lastBotIdx = i;
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if (lastBotIdx === -1) {
|
|
572
|
+
console.log(c('yellow', ' 没有可重新生成的回复'));
|
|
573
|
+
await sleep(1000);
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// 删除客户端的 AI 回复(以及之后的 system 消息)
|
|
578
|
+
messages.splice(lastBotIdx);
|
|
579
|
+
drawMessages();
|
|
580
|
+
|
|
581
|
+
// 显示思考中
|
|
582
|
+
process.stdout.write(c('bot', ` ${currentCharacter.name}: `) + c('hint', '重新生成中...'));
|
|
583
|
+
|
|
584
|
+
try {
|
|
585
|
+
const response = await regenerateMessage(currentConversationId);
|
|
586
|
+
process.stdout.write('\r\x1b[K');
|
|
587
|
+
process.stdout.write(c('bot', ` ${currentCharacter.name}: `));
|
|
588
|
+
|
|
589
|
+
let fullResponse = '';
|
|
590
|
+
const reader = response.body.getReader();
|
|
591
|
+
const decoder = new TextDecoder();
|
|
592
|
+
let buffer = '';
|
|
593
|
+
|
|
594
|
+
while (true) {
|
|
595
|
+
const { done, value } = await reader.read();
|
|
596
|
+
if (done) break;
|
|
597
|
+
buffer += decoder.decode(value, { stream: true });
|
|
598
|
+
const lines = buffer.split('\n');
|
|
599
|
+
buffer = lines.pop() || '';
|
|
600
|
+
|
|
601
|
+
for (const line of lines) {
|
|
602
|
+
if (line.startsWith('data: ')) {
|
|
603
|
+
const data = line.slice(6);
|
|
604
|
+
if (data === '[DONE]') continue;
|
|
605
|
+
try {
|
|
606
|
+
const json = JSON.parse(data);
|
|
607
|
+
if (json.type === 'tool_call') {
|
|
608
|
+
process.stdout.write('\r\x1b[K');
|
|
609
|
+
process.stdout.write(c('cyan', ` 🔍 正在搜索: ${json.query}...`));
|
|
610
|
+
messages.push({ role: 'system', text: `🔍 正在搜索: ${json.query}` });
|
|
611
|
+
} else if (json.type === 'tool_result') {
|
|
612
|
+
process.stdout.write('\r\x1b[K');
|
|
613
|
+
process.stdout.write(c('green', ` 📋 找到 ${json.count} 条结果\n`));
|
|
614
|
+
process.stdout.write(c('bot', ` ${currentCharacter.name}: `));
|
|
615
|
+
messages.push({ role: 'system', text: `📋 找到 ${json.count} 条结果` });
|
|
616
|
+
} else if (json.type === 'content') {
|
|
617
|
+
fullResponse += json.content;
|
|
618
|
+
process.stdout.write(json.content);
|
|
603
619
|
}
|
|
604
|
-
}
|
|
620
|
+
} catch {}
|
|
605
621
|
}
|
|
606
|
-
|
|
607
|
-
console.log();
|
|
608
|
-
messages.push({ role: 'bot', text: fullResponse || '...', timestamp: new Date() });
|
|
609
|
-
drawMessages();
|
|
610
|
-
} catch (err) {
|
|
611
|
-
process.stdout.write('\r\x1b[K');
|
|
612
|
-
console.log(c('red', ` 错误: ${err.message}`));
|
|
613
|
-
await sleep(1500);
|
|
614
622
|
}
|
|
615
623
|
}
|
|
624
|
+
|
|
625
|
+
console.log();
|
|
626
|
+
messages.push({ role: 'bot', text: fullResponse || '...', timestamp: new Date() });
|
|
627
|
+
drawMessages();
|
|
628
|
+
} catch (err) {
|
|
629
|
+
process.stdout.write('\r\x1b[K');
|
|
630
|
+
console.log(c('red', ` 错误: ${err.message}`));
|
|
631
|
+
await sleep(1500);
|
|
616
632
|
}
|
|
617
633
|
continue;
|
|
618
634
|
}
|