Spaces:
Build error
Build error
import { | |
chat_metadata, | |
eventSource, | |
event_types, | |
getTokenCount, | |
saveSettingsDebounced, | |
this_chid, | |
} from "../script.js"; | |
import { selected_group } from "./group-chats.js"; | |
import { extension_settings, getContext, saveMetadataDebounced } from "./extensions.js"; | |
import { registerSlashCommand } from "./slash-commands.js"; | |
import { getCharaFilename, debounce, waitUntilCondition, delay } from "./utils.js"; | |
export { MODULE_NAME as NOTE_MODULE_NAME }; | |
const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory | |
const DEFAULT_DEPTH = 4; | |
const DEFAULT_POSITION = 1; | |
const DEFAULT_INTERVAL = 1; | |
export var shouldWIAddPrompt = false; | |
export const metadata_keys = { | |
prompt: 'note_prompt', | |
interval: 'note_interval', | |
depth: 'note_depth', | |
position: 'note_position', | |
} | |
const chara_note_position = { | |
replace: 0, | |
before: 1, | |
after: 2, | |
} | |
function setNoteTextCommand(_, text) { | |
$('#extension_floating_prompt').val(text).trigger('input'); | |
toastr.success("Author's Note text updated"); | |
} | |
function setNoteDepthCommand(_, text) { | |
const value = Number(text); | |
if (Number.isNaN(value)) { | |
toastr.error('Not a valid number'); | |
return; | |
} | |
$('#extension_floating_depth').val(Math.abs(value)).trigger('input'); | |
toastr.success("Author's Note depth updated"); | |
} | |
function setNoteIntervalCommand(_, text) { | |
const value = Number(text); | |
if (Number.isNaN(value)) { | |
toastr.error('Not a valid number'); | |
return; | |
} | |
$('#extension_floating_interval').val(Math.abs(value)).trigger('input'); | |
toastr.success("Author's Note frequency updated"); | |
} | |
function setNotePositionCommand(_, text) { | |
const validPositions = { | |
'scenario': 0, | |
'chat': 1, | |
}; | |
const position = validPositions[text?.trim()]; | |
if (Number.isNaN(position)) { | |
toastr.error('Not a valid position'); | |
return; | |
} | |
$(`input[name="extension_floating_position"][value="${position}"]`).prop('checked', true).trigger('input'); | |
toastr.info("Author's Note position updated"); | |
} | |
function updateSettings() { | |
saveSettingsDebounced(); | |
loadSettings(); | |
setFloatingPrompt(); | |
} | |
const setMainPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_prompt_token_counter').text(getTokenCount(value)), 1000); | |
const setCharaPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_chara_token_counter').text(getTokenCount(value)), 1000); | |
const setDefaultPromptTokenCounterDebounced = debounce((value) => $('#extension_floating_default_token_counter').text(getTokenCount(value)), 1000); | |
async function onExtensionFloatingPromptInput() { | |
chat_metadata[metadata_keys.prompt] = $(this).val(); | |
setMainPromptTokenCounterDebounced(chat_metadata[metadata_keys.prompt]); | |
updateSettings(); | |
saveMetadataDebounced(); | |
} | |
async function onExtensionFloatingIntervalInput() { | |
chat_metadata[metadata_keys.interval] = Number($(this).val()); | |
updateSettings(); | |
saveMetadataDebounced(); | |
} | |
async function onExtensionFloatingDepthInput() { | |
let value = Number($(this).val()); | |
if (value < 0) { | |
value = Math.abs(value); | |
$(this).val(value); | |
} | |
chat_metadata[metadata_keys.depth] = value; | |
updateSettings(); | |
saveMetadataDebounced(); | |
} | |
async function onExtensionFloatingPositionInput(e) { | |
chat_metadata[metadata_keys.position] = e.target.value; | |
updateSettings(); | |
saveMetadataDebounced(); | |
} | |
async function onExtensionFloatingCharPositionInput(e) { | |
const value = e.target.value; | |
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename()); | |
if (charaNote) { | |
charaNote.position = Number(value); | |
updateSettings(); | |
} | |
} | |
function onExtensionFloatingCharaPromptInput() { | |
const tempPrompt = $(this).val(); | |
const avatarName = getCharaFilename(); | |
let tempCharaNote = { | |
name: avatarName, | |
prompt: tempPrompt | |
} | |
setCharaPromptTokenCounterDebounced(tempPrompt); | |
let existingCharaNoteIndex; | |
let existingCharaNote; | |
if (extension_settings.note.chara) { | |
existingCharaNoteIndex = extension_settings.note.chara.findIndex((e) => e.name === avatarName); | |
existingCharaNote = extension_settings.note.chara[existingCharaNoteIndex] | |
} | |
if (tempPrompt.length === 0 && | |
extension_settings.note.chara && | |
existingCharaNote && | |
!existingCharaNote.useChara | |
) { | |
extension_settings.note.chara.splice(existingCharaNoteIndex, 1); | |
} | |
else if (extension_settings.note.chara && existingCharaNote) { | |
Object.assign(existingCharaNote, tempCharaNote); | |
} | |
else if (avatarName && tempPrompt.length > 0) { | |
if (!extension_settings.note.chara) { | |
extension_settings.note.chara = [] | |
} | |
Object.assign(tempCharaNote, { useChara: false, position: chara_note_position.replace }) | |
extension_settings.note.chara.push(tempCharaNote); | |
} else { | |
console.log("Character author's note error: No avatar name key could be found."); | |
toastr.error("Something went wrong. Could not save character's author's note."); | |
// Don't save settings if something went wrong | |
return; | |
} | |
updateSettings(); | |
} | |
function onExtensionFloatingCharaCheckboxChanged() { | |
const value = !!$(this).prop('checked'); | |
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename()); | |
if (charaNote) { | |
charaNote.useChara = value; | |
updateSettings(); | |
} | |
} | |
function onExtensionFloatingDefaultInput() { | |
extension_settings.note.default = $(this).val(); | |
setDefaultPromptTokenCounterDebounced(extension_settings.note.default); | |
updateSettings(); | |
} | |
function loadSettings() { | |
chat_metadata[metadata_keys.prompt] = chat_metadata[metadata_keys.prompt] ?? extension_settings.note.default ?? ''; | |
chat_metadata[metadata_keys.interval] = chat_metadata[metadata_keys.interval] ?? DEFAULT_INTERVAL; | |
chat_metadata[metadata_keys.position] = chat_metadata[metadata_keys.position] ?? DEFAULT_POSITION; | |
chat_metadata[metadata_keys.depth] = chat_metadata[metadata_keys.depth] ?? DEFAULT_DEPTH; | |
$('#extension_floating_prompt').val(chat_metadata[metadata_keys.prompt]); | |
$('#extension_floating_interval').val(chat_metadata[metadata_keys.interval]); | |
$('#extension_floating_depth').val(chat_metadata[metadata_keys.depth]); | |
$(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true); | |
if (extension_settings.note.chara && getContext().characterId) { | |
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename()); | |
$('#extension_floating_chara').val(charaNote ? charaNote.prompt : ''); | |
$('#extension_use_floating_chara').prop('checked', charaNote ? charaNote.useChara : false); | |
$(`input[name="extension_floating_char_position"][value="${charaNote?.position ?? chara_note_position.replace}"]`).prop('checked', true); | |
} else { | |
$('#extension_floating_chara').val(''); | |
$('#extension_use_floating_chara').prop('checked', false); | |
$(`input[name="extension_floating_char_position"][value="${chara_note_position.replace}"]`).prop('checked', true); | |
} | |
$('#extension_floating_default').val(extension_settings.note.default); | |
} | |
export function setFloatingPrompt() { | |
const context = getContext(); | |
if (!context.groupId && context.characterId === undefined) { | |
console.debug('setFloatingPrompt: Not in a chat. Skipping.'); | |
shouldWIAddPrompt = false; | |
return; | |
} | |
// take the count of messages | |
let lastMessageNumber = Array.isArray(context.chat) && context.chat.length ? context.chat.filter(m => m.is_user).length : 0; | |
console.debug(` | |
setFloatingPrompt entered | |
------ | |
lastMessageNumber = ${lastMessageNumber} | |
metadata_keys.interval = ${chat_metadata[metadata_keys.interval]} | |
`) | |
// interval 1 should be inserted no matter what | |
if (chat_metadata[metadata_keys.interval] === 1) { | |
lastMessageNumber = 1; | |
} | |
if (lastMessageNumber <= 0 || chat_metadata[metadata_keys.interval] <= 0) { | |
context.setExtensionPrompt(MODULE_NAME, ''); | |
$('#extension_floating_counter').text('(disabled)'); | |
shouldWIAddPrompt = false; | |
return; | |
} | |
const messagesTillInsertion = lastMessageNumber >= chat_metadata[metadata_keys.interval] | |
? (lastMessageNumber % chat_metadata[metadata_keys.interval]) | |
: (chat_metadata[metadata_keys.interval] - lastMessageNumber); | |
const shouldAddPrompt = messagesTillInsertion == 0; | |
shouldWIAddPrompt = shouldAddPrompt; | |
let prompt = shouldAddPrompt ? $('#extension_floating_prompt').val() : ''; | |
if (shouldAddPrompt && extension_settings.note.chara && getContext().characterId) { | |
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename()); | |
// Only replace with the chara note if the user checked the box | |
if (charaNote && charaNote.useChara) { | |
switch (charaNote.position) { | |
case chara_note_position.before: | |
prompt = charaNote.prompt + '\n' + prompt; | |
break; | |
case chara_note_position.after: | |
prompt = prompt + '\n' + charaNote.prompt; | |
break; | |
default: | |
prompt = charaNote.prompt; | |
break; | |
} | |
} | |
} | |
context.setExtensionPrompt(MODULE_NAME, prompt, chat_metadata[metadata_keys.position], chat_metadata[metadata_keys.depth]); | |
$('#extension_floating_counter').text(shouldAddPrompt ? '0' : messagesTillInsertion); | |
} | |
function onANMenuItemClick() { | |
if (selected_group || this_chid) { | |
//show AN if it's hidden | |
if ($("#floatingPrompt").css("display") !== 'flex') { | |
$("#floatingPrompt").addClass('resizing') | |
$("#floatingPrompt").css("display", "flex"); | |
$("#floatingPrompt").css("opacity", 0.0); | |
$("#floatingPrompt").transition({ | |
opacity: 1.0, | |
duration: 250, | |
}, async function () { | |
await delay(50); | |
$("#floatingPrompt").removeClass('resizing') | |
}); | |
//auto-open the main AN inline drawer | |
if ($("#ANBlockToggle") | |
.siblings('.inline-drawer-content') | |
.css('display') !== 'block') { | |
$("#floatingPrompt").addClass('resizing') | |
$("#ANBlockToggle").click(); | |
} | |
} else { | |
//hide AN if it's already displayed | |
$("#floatingPrompt").addClass('resizing') | |
$("#floatingPrompt").transition({ | |
opacity: 0.0, | |
duration: 250, | |
}, | |
async function () { | |
await delay(50); | |
$("#floatingPrompt").removeClass('resizing') | |
}); | |
setTimeout(function () { | |
$("#floatingPrompt").hide(); | |
}, 250); | |
} | |
//duplicate options menu close handler from script.js | |
//because this listener takes priority | |
$("#options").stop().fadeOut(250); | |
} else { | |
toastr.warning(`Select a character before trying to use Author's Note`, '', { timeOut: 2000 }); | |
} | |
} | |
function onChatChanged() { | |
loadSettings(); | |
setFloatingPrompt(); | |
const context = getContext(); | |
// Disable the chara note if in a group | |
$('#extension_floating_chara').prop('disabled', context.groupId ? true : false); | |
const tokenCounter1 = chat_metadata[metadata_keys.prompt] ? getTokenCount(chat_metadata[metadata_keys.prompt]) : 0; | |
$('#extension_floating_prompt_token_counter').text(tokenCounter1); | |
let tokenCounter2; | |
if (extension_settings.note.chara && context.characterId) { | |
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename()); | |
if (charaNote) { | |
tokenCounter2 = getTokenCount(charaNote.prompt); | |
} | |
} | |
if (tokenCounter2) { | |
$('#extension_floating_chara_token_counter').text(tokenCounter2); | |
} | |
const tokenCounter3 = extension_settings.note.default ? getTokenCount(extension_settings.note.default) : 0; | |
$('#extension_floating_default_token_counter').text(tokenCounter3); | |
} | |
// Inject extension when extensions_activating is fired | |
// Inserts the extension first since it's statically imported | |
jQuery(async () => { | |
await waitUntilCondition(() => eventSource !== undefined); | |
$('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput); | |
$('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput); | |
$('#extension_floating_depth').on('input', onExtensionFloatingDepthInput); | |
$('#extension_floating_chara').on('input', onExtensionFloatingCharaPromptInput); | |
$('#extension_use_floating_chara').on('input', onExtensionFloatingCharaCheckboxChanged); | |
$('#extension_floating_default').on('input', onExtensionFloatingDefaultInput); | |
$('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput); | |
$('input[name="extension_floating_char_position"]').on('change', onExtensionFloatingCharPositionInput); | |
$('#ANClose').on('click', function () { | |
$("#floatingPrompt").transition({ | |
opacity: 0, | |
duration: 200, | |
easing: 'ease-in-out', | |
}); | |
setTimeout(function () { $('#floatingPrompt').hide() }, 200); | |
}) | |
$("#option_toggle_AN").on('click', onANMenuItemClick); | |
registerSlashCommand('note', setNoteTextCommand, [], "<span class='monospace'>(text)</span> β sets an author's note for the currently selected chat", true, true); | |
registerSlashCommand('depth', setNoteDepthCommand, [], "<span class='monospace'>(number)</span> β sets an author's note depth for in-chat positioning", true, true); | |
registerSlashCommand('freq', setNoteIntervalCommand, ['interval'], "<span class='monospace'>(number)</span> β sets an author's note insertion frequency", true, true); | |
registerSlashCommand('pos', setNotePositionCommand, ['position'], "(<span class='monospace'>chat</span> or <span class='monospace'>scenario</span>) β sets an author's note position", true, true); | |
eventSource.on(event_types.CHAT_CHANGED, onChatChanged); | |
}); | |