Chat without character selected (#2757)
* WIP: Enable chatting without character selected * Add burger menu item * Neutral assistant chat space * Revert "Neutral assistant chat space" This reverts commitbe2da4a629
. * Revert "Add burger menu item" This reverts commitd4e8d990c1
. * Use simple ephemeral chats * Only start a new assistant chat if not already in it * Don't emit event not to clear pending files * Allow edits, disable checkpoints and branches * Exclude from tags, allow copy * Allow hide/unhide * Allow zooming avatar * Suppress warning * Rename neutral character * Rename neutral back to Assistant
This commit is contained in:
parent
b16915cfb9
commit
f7de495321
|
@ -484,9 +484,10 @@ const promptStorage = new localforage.createInstance({ name: 'SillyTavern_Prompt
|
||||||
export let itemizedPrompts = [];
|
export let itemizedPrompts = [];
|
||||||
|
|
||||||
export const systemUserName = 'SillyTavern System';
|
export const systemUserName = 'SillyTavern System';
|
||||||
|
export const neutralCharacterName = 'Assistant';
|
||||||
let default_user_name = 'User';
|
let default_user_name = 'User';
|
||||||
export let name1 = default_user_name;
|
export let name1 = default_user_name;
|
||||||
export let name2 = 'SillyTavern System';
|
export let name2 = systemUserName;
|
||||||
export let chat = [];
|
export let chat = [];
|
||||||
let chatSaveTimeout;
|
let chatSaveTimeout;
|
||||||
let importFlashTimeout;
|
let importFlashTimeout;
|
||||||
|
@ -563,6 +564,8 @@ export const system_message_types = {
|
||||||
FORMATTING: 'formatting',
|
FORMATTING: 'formatting',
|
||||||
HOTKEYS: 'hotkeys',
|
HOTKEYS: 'hotkeys',
|
||||||
MACROS: 'macros',
|
MACROS: 'macros',
|
||||||
|
WELCOME_PROMPT: 'welcome_prompt',
|
||||||
|
ASSISTANT_NOTE: 'assistant_note',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -680,6 +683,26 @@ async function getSystemMessages() {
|
||||||
is_system: true,
|
is_system: true,
|
||||||
mes: 'Click here to return to the previous chat: <a class="bookmark_link" file_name="{0}" href="javascript:void(null);">Return</a>',
|
mes: 'Click here to return to the previous chat: <a class="bookmark_link" file_name="{0}" href="javascript:void(null);">Return</a>',
|
||||||
},
|
},
|
||||||
|
welcome_prompt: {
|
||||||
|
name: systemUserName,
|
||||||
|
force_avatar: system_avatar,
|
||||||
|
is_user: false,
|
||||||
|
is_system: true,
|
||||||
|
mes: await renderTemplateAsync('welcomePrompt'),
|
||||||
|
extra: {
|
||||||
|
isSmallSys: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
assistant_note: {
|
||||||
|
name: systemUserName,
|
||||||
|
force_avatar: system_avatar,
|
||||||
|
is_user: false,
|
||||||
|
is_system: true,
|
||||||
|
mes: await renderTemplateAsync('assistantNote'),
|
||||||
|
extra: {
|
||||||
|
isSmallSys: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,6 +947,7 @@ async function firstLoadInit() {
|
||||||
initTextGenModels();
|
initTextGenModels();
|
||||||
await getSystemMessages();
|
await getSystemMessages();
|
||||||
sendSystemMessage(system_message_types.WELCOME);
|
sendSystemMessage(system_message_types.WELCOME);
|
||||||
|
sendSystemMessage(system_message_types.WELCOME_PROMPT);
|
||||||
await getSettings();
|
await getSettings();
|
||||||
initKeyboard();
|
initKeyboard();
|
||||||
initDynamicStyles();
|
initDynamicStyles();
|
||||||
|
@ -1849,7 +1873,7 @@ export async function reloadCurrentChat() {
|
||||||
/**
|
/**
|
||||||
* Send the message currently typed into the chat box.
|
* Send the message currently typed into the chat box.
|
||||||
*/
|
*/
|
||||||
export function sendTextareaMessage() {
|
export async function sendTextareaMessage() {
|
||||||
if (is_send_press) return;
|
if (is_send_press) return;
|
||||||
if (isExecutingCommandsFromChatInput) return;
|
if (isExecutingCommandsFromChatInput) return;
|
||||||
|
|
||||||
|
@ -1867,6 +1891,10 @@ export function sendTextareaMessage() {
|
||||||
generateType = 'continue';
|
generateType = 'continue';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (textareaText && !selected_group && this_chid === undefined && name2 !== neutralCharacterName) {
|
||||||
|
await newAssistantChat();
|
||||||
|
}
|
||||||
|
|
||||||
Generate(generateType);
|
Generate(generateType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1946,9 +1974,7 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId) {
|
||||||
mes = mes.replaceAll('<', '<').replaceAll('>', '>');
|
mes = mes.replaceAll('<', '<').replaceAll('>', '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this_chid === undefined && !selected_group) {
|
if (!isSystem) {
|
||||||
mes = mes.replace(/\*\*(.+?)\*\*/g, '<b>$1</b>');
|
|
||||||
} else if (!isSystem) {
|
|
||||||
// Save double quotes in tags as a special character to prevent them from being encoded
|
// Save double quotes in tags as a special character to prevent them from being encoded
|
||||||
if (!power_user.encode_tags) {
|
if (!power_user.encode_tags) {
|
||||||
mes = mes.replace(/<([^>]+)>/g, function (_, contents) {
|
mes = mes.replace(/<([^>]+)>/g, function (_, contents) {
|
||||||
|
@ -1987,13 +2013,6 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Hides bias from empty messages send with slash commands
|
|
||||||
if (isSystem) {
|
|
||||||
mes = mes.replace(/\{\{[\s\S]*?\}\}/gm, "");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!power_user.allow_name2_display && ch_name && !isUser && !isSystem) {
|
if (!power_user.allow_name2_display && ch_name && !isUser && !isSystem) {
|
||||||
mes = mes.replace(new RegExp(`(^|\n)${escapeRegex(ch_name)}:`, 'g'), '$1');
|
mes = mes.replace(new RegExp(`(^|\n)${escapeRegex(ch_name)}:`, 'g'), '$1');
|
||||||
}
|
}
|
||||||
|
@ -3400,14 +3419,11 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
||||||
quiet_prompt = main_api == 'novel' && !quietToLoud ? adjustNovelInstructionPrompt(quiet_prompt) : quiet_prompt;
|
quiet_prompt = main_api == 'novel' && !quietToLoud ? adjustNovelInstructionPrompt(quiet_prompt) : quiet_prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isChatValid = online_status !== 'no_connection' && this_chid !== undefined;
|
const hasBackendConnection = online_status !== 'no_connection';
|
||||||
|
|
||||||
// We can't do anything because we're not in a chat right now. (Unless it's a dry run, in which case we need to
|
// We can't do anything because we're not in a chat right now. (Unless it's a dry run, in which case we need to
|
||||||
// assemble the prompt so we can count its tokens regardless of whether a chat is active.)
|
// assemble the prompt so we can count its tokens regardless of whether a chat is active.)
|
||||||
if (!dryRun && !isChatValid) {
|
if (!dryRun && !hasBackendConnection) {
|
||||||
if (this_chid === undefined) {
|
|
||||||
toastr.warning('Сharacter is not selected');
|
|
||||||
}
|
|
||||||
is_send_press = false;
|
is_send_press = false;
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -3493,9 +3509,9 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
||||||
setExtensionPrompt('DEPTH_PROMPT_' + index, value.text, extension_prompt_types.IN_CHAT, value.depth, extension_settings.note.allowWIScan, role);
|
setExtensionPrompt('DEPTH_PROMPT_' + index, value.text, extension_prompt_types.IN_CHAT, value.depth, extension_settings.note.allowWIScan, role);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const depthPromptText = baseChatReplace(characters[this_chid].data?.extensions?.depth_prompt?.prompt?.trim(), name1, name2) || '';
|
const depthPromptText = baseChatReplace(characters[this_chid]?.data?.extensions?.depth_prompt?.prompt?.trim(), name1, name2) || '';
|
||||||
const depthPromptDepth = characters[this_chid].data?.extensions?.depth_prompt?.depth ?? depth_prompt_depth_default;
|
const depthPromptDepth = characters[this_chid]?.data?.extensions?.depth_prompt?.depth ?? depth_prompt_depth_default;
|
||||||
const depthPromptRole = getExtensionPromptRoleByName(characters[this_chid].data?.extensions?.depth_prompt?.role ?? depth_prompt_role_default);
|
const depthPromptRole = getExtensionPromptRoleByName(characters[this_chid]?.data?.extensions?.depth_prompt?.role ?? depth_prompt_role_default);
|
||||||
setExtensionPrompt('DEPTH_PROMPT', depthPromptText, extension_prompt_types.IN_CHAT, depthPromptDepth, extension_settings.note.allowWIScan, depthPromptRole);
|
setExtensionPrompt('DEPTH_PROMPT', depthPromptText, extension_prompt_types.IN_CHAT, depthPromptDepth, extension_settings.note.allowWIScan, depthPromptRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5905,11 +5921,16 @@ export function saveChatDebounced() {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveChat(chat_name, withMetadata, mesId) {
|
export async function saveChat(chatName, withMetadata, mesId) {
|
||||||
const metadata = { ...chat_metadata, ...(withMetadata || {}) };
|
const metadata = { ...chat_metadata, ...(withMetadata || {}) };
|
||||||
let file_name = chat_name ?? characters[this_chid]?.chat;
|
const fileName = chatName ?? characters[this_chid]?.chat;
|
||||||
|
|
||||||
if (!file_name) {
|
if (!fileName && name2 === neutralCharacterName) {
|
||||||
|
// TODO: Do something for a temporary chat with no character.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileName) {
|
||||||
console.warn('saveChat called without chat_name and no chat file found');
|
console.warn('saveChat called without chat_name and no chat file found');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5950,7 +5971,7 @@ export async function saveChat(chat_name, withMetadata, mesId) {
|
||||||
url: '/api/chats/save',
|
url: '/api/chats/save',
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
ch_name: characters[this_chid].name,
|
ch_name: characters[this_chid].name,
|
||||||
file_name: file_name,
|
file_name: fileName,
|
||||||
chat: save_chat,
|
chat: save_chat,
|
||||||
avatar_url: characters[this_chid].avatar,
|
avatar_url: characters[this_chid].avatar,
|
||||||
}),
|
}),
|
||||||
|
@ -6665,7 +6686,7 @@ function updateMessage(div) {
|
||||||
function openMessageDelete(fromSlashCommand) {
|
function openMessageDelete(fromSlashCommand) {
|
||||||
closeMessageEditor();
|
closeMessageEditor();
|
||||||
hideSwipeButtons();
|
hideSwipeButtons();
|
||||||
if (fromSlashCommand || (this_chid != undefined && !is_send_press) || (selected_group && !is_group_generating)) {
|
if (fromSlashCommand || (!is_send_press) || (selected_group && !is_group_generating)) {
|
||||||
$('#dialogue_del_mes').css('display', 'block');
|
$('#dialogue_del_mes').css('display', 'block');
|
||||||
$('#send_form').css('display', 'none');
|
$('#send_form').css('display', 'none');
|
||||||
$('.del_checkbox').each(function () {
|
$('.del_checkbox').each(function () {
|
||||||
|
@ -8218,6 +8239,11 @@ function swipe_left() { // when we swipe left..but no generation.
|
||||||
* @returns {Promise<string>} Branch file name
|
* @returns {Promise<string>} Branch file name
|
||||||
*/
|
*/
|
||||||
async function branchChat(mesId) {
|
async function branchChat(mesId) {
|
||||||
|
if (this_chid === undefined && !selected_group) {
|
||||||
|
toastr.info('No character selected.', 'Branch creation aborted');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const fileName = await createBranch(mesId);
|
const fileName = await createBranch(mesId);
|
||||||
await saveItemizedPrompts(fileName);
|
await saveItemizedPrompts(fileName);
|
||||||
|
|
||||||
|
@ -8955,6 +8981,14 @@ async function removeCharacterFromUI() {
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function newAssistantChat() {
|
||||||
|
await clearChat();
|
||||||
|
chat.splice(0, chat.length);
|
||||||
|
chat_metadata = {};
|
||||||
|
setCharacterName(neutralCharacterName);
|
||||||
|
sendSystemMessage(system_message_types.ASSISTANT_NOTE);
|
||||||
|
}
|
||||||
|
|
||||||
function doTogglePanels() {
|
function doTogglePanels() {
|
||||||
$('#option_settings').trigger('click');
|
$('#option_settings').trigger('click');
|
||||||
return '';
|
return '';
|
||||||
|
@ -9800,6 +9834,9 @@ jQuery(async function () {
|
||||||
|
|
||||||
await doNewChat({ deleteCurrentChat: deleteCurrentChat });
|
await doNewChat({ deleteCurrentChat: deleteCurrentChat });
|
||||||
}
|
}
|
||||||
|
if (!selected_group && this_chid === undefined && !is_send_press) {
|
||||||
|
await newAssistantChat();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (id == 'option_regenerate') {
|
else if (id == 'option_regenerate') {
|
||||||
|
@ -9850,6 +9887,7 @@ jQuery(async function () {
|
||||||
$('#rm_button_selected_ch').children('h2').text('');
|
$('#rm_button_selected_ch').children('h2').text('');
|
||||||
select_rm_characters();
|
select_rm_characters();
|
||||||
sendSystemMessage(system_message_types.WELCOME);
|
sendSystemMessage(system_message_types.WELCOME);
|
||||||
|
sendSystemMessage(system_message_types.WELCOME_PROMPT);
|
||||||
eventSource.emit(event_types.CHAT_CHANGED, getCurrentChatId());
|
eventSource.emit(event_types.CHAT_CHANGED, getCurrentChatId());
|
||||||
await getClientVersion();
|
await getClientVersion();
|
||||||
} else {
|
} else {
|
||||||
|
@ -10048,7 +10086,7 @@ jQuery(async function () {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$(document).on('pointerup', '.mes_copy', function () {
|
$(document).on('pointerup', '.mes_copy', function () {
|
||||||
if (this_chid !== undefined || selected_group) {
|
if (this_chid !== undefined || selected_group || name2 === neutralCharacterName) {
|
||||||
try {
|
try {
|
||||||
const messageId = $(this).closest('.mes').attr('mesid');
|
const messageId = $(this).closest('.mes').attr('mesid');
|
||||||
const text = chat[messageId]['mes'];
|
const text = chat[messageId]['mes'];
|
||||||
|
@ -10072,7 +10110,7 @@ jQuery(async function () {
|
||||||
//********************
|
//********************
|
||||||
//***Message Editor***
|
//***Message Editor***
|
||||||
$(document).on('click', '.mes_edit', async function () {
|
$(document).on('click', '.mes_edit', async function () {
|
||||||
if (this_chid !== undefined || selected_group) {
|
if (this_chid !== undefined || selected_group || name2 === neutralCharacterName) {
|
||||||
// Previously system messages we're allowed to be edited
|
// Previously system messages we're allowed to be edited
|
||||||
/*const message = $(this).closest(".mes");
|
/*const message = $(this).closest(".mes");
|
||||||
|
|
||||||
|
@ -10664,7 +10702,7 @@ jQuery(async function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const avatarSrc = isDataURL(thumbURL) ? thumbURL : charsPath + targetAvatarImg;
|
const avatarSrc = (isDataURL(thumbURL) || /^\/?img\/(?:.+)/.test(thumbURL)) ? thumbURL : charsPath + targetAvatarImg;
|
||||||
if ($(`.zoomed_avatar[forChar="${charname}"]`).length) {
|
if ($(`.zoomed_avatar[forChar="${charname}"]`).length) {
|
||||||
console.debug('removing container as it already existed');
|
console.debug('removing container as it already existed');
|
||||||
$(`.zoomed_avatar[forChar="${charname}"]`).fadeOut(animation_duration, () => {
|
$(`.zoomed_avatar[forChar="${charname}"]`).fadeOut(animation_duration, () => {
|
||||||
|
|
|
@ -168,6 +168,11 @@ export async function createBranch(mesId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNewBookmark(mesId) {
|
async function createNewBookmark(mesId) {
|
||||||
|
if (this_chid === undefined && !selected_group) {
|
||||||
|
toastr.info('No character selected.', 'Checkpoint creation aborted');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!chat.length) {
|
if (!chat.length) {
|
||||||
toastr.warning('The chat is empty.', 'Checkpoint creation failed');
|
toastr.warning('The chat is empty.', 'Checkpoint creation failed');
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -125,8 +125,6 @@ function getConverter(type) {
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export async function hideChatMessageRange(start, end, unhide) {
|
export async function hideChatMessageRange(start, end, unhide) {
|
||||||
if (!getCurrentChatId()) return;
|
|
||||||
|
|
||||||
if (isNaN(start)) return;
|
if (isNaN(start)) return;
|
||||||
if (!end) end = start;
|
if (!end) end = start;
|
||||||
const hide = !unhide;
|
const hide = !unhide;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<div>
|
||||||
|
<b>Note:</b> this chat is temporary and will be deleted as soon as you leave it.
|
||||||
|
</div>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<strong data-i18n="Connect to an API and ask me anything!">
|
||||||
|
Connect to an API and ask me anything!
|
||||||
|
</strong>
|
Loading…
Reference in New Issue