mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-03-02 19:07:40 +01:00
Merge branch 'wi-regex-keys' of https://github.com/Wolfsblvt/SillyTavern into wi-regex-keys
This commit is contained in:
commit
6c2dc6756b
11
package-lock.json
generated
11
package-lock.json
generated
@ -12,7 +12,6 @@
|
||||
"dependencies": {
|
||||
"@agnai/sentencepiece-js": "^1.1.1",
|
||||
"@agnai/web-tokenizers": "^0.1.3",
|
||||
"@dqbd/tiktoken": "^1.0.13",
|
||||
"@zeldafan0225/ai_horde": "^4.0.1",
|
||||
"archiver": "^7.0.1",
|
||||
"bing-translate-api": "^2.9.1",
|
||||
@ -46,6 +45,7 @@
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sillytavern-transformers": "^2.14.6",
|
||||
"simple-git": "^3.19.1",
|
||||
"tiktoken": "^1.0.15",
|
||||
"vectra": "^0.2.2",
|
||||
"wavefile": "^11.0.0",
|
||||
"write-file-atomic": "^5.0.1",
|
||||
@ -82,10 +82,6 @@
|
||||
"version": "0.1.3",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@dqbd/tiktoken": {
|
||||
"version": "1.0.13",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"dev": true,
|
||||
@ -4403,6 +4399,11 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tiktoken": {
|
||||
"version": "1.0.15",
|
||||
"resolved": "https://registry.npmjs.org/tiktoken/-/tiktoken-1.0.15.tgz",
|
||||
"integrity": "sha512-sCsrq/vMWUSEW29CJLNmPvWxlVp7yh2tlkAjpJltIKqp5CKf98ZNpdeHRmAlPVFlGEbswDc6SmI8vz64W/qErw=="
|
||||
},
|
||||
"node_modules/timm": {
|
||||
"version": "1.7.1",
|
||||
"license": "MIT"
|
||||
|
@ -2,7 +2,6 @@
|
||||
"dependencies": {
|
||||
"@agnai/sentencepiece-js": "^1.1.1",
|
||||
"@agnai/web-tokenizers": "^0.1.3",
|
||||
"@dqbd/tiktoken": "^1.0.13",
|
||||
"@zeldafan0225/ai_horde": "^4.0.1",
|
||||
"archiver": "^7.0.1",
|
||||
"bing-translate-api": "^2.9.1",
|
||||
@ -36,6 +35,7 @@
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"sillytavern-transformers": "^2.14.6",
|
||||
"simple-git": "^3.19.1",
|
||||
"tiktoken": "^1.0.15",
|
||||
"vectra": "^0.2.2",
|
||||
"wavefile": "^11.0.0",
|
||||
"write-file-atomic": "^5.0.1",
|
||||
|
@ -102,7 +102,7 @@
|
||||
height: auto;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
min-height: calc(var(--mainFontSize) + 13px);
|
||||
min-height: calc(var(--mainFontSize) + 14px);
|
||||
}
|
||||
|
||||
.delete_entry_button {
|
||||
|
@ -5292,6 +5292,12 @@
|
||||
Prevent further recursion (this entry will not activate others)
|
||||
</span>
|
||||
</label>
|
||||
<label class="checkbox flex-container alignitemscenter flexNoGap">
|
||||
<input type="checkbox" name="delay_until_recursion" />
|
||||
<span data-i18n="Delay until recursion (this entry can only be activated on recursive checking)">
|
||||
Delay until recursion (this entry can only be activated on recursive checking)
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</span>
|
||||
</small>
|
||||
@ -5332,7 +5338,7 @@
|
||||
<div class="flex-container justifySpaceBetween">
|
||||
<small for="group" data-i18n="Inclusion Group">
|
||||
Inclusion Group
|
||||
<a href="https://docs.sillytavern.app/usage/core-concepts/worldinfo/#inclusion-group" class="notes-link" target="_blank" title="Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered. Documentation: World Info - Inclusion Group" data-i18n="[title]Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered. Documentation: World Info - Inclusion Group">
|
||||
<a href="https://docs.sillytavern.app/usage/core-concepts/worldinfo/#inclusion-group" class="notes-link" target="_blank" title="Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered. Supports multiple comma-separated groups. Documentation: World Info - Inclusion Group" data-i18n="[title]Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered. Documentation: World Info - Inclusion Group">
|
||||
<span class="fa-solid fa-circle-question note-link-span"></span>
|
||||
</a>
|
||||
</small>
|
||||
|
113
public/script.js
113
public/script.js
@ -415,6 +415,7 @@ export const event_types = {
|
||||
GROUP_MEMBER_DRAFTED: 'group_member_drafted',
|
||||
WORLD_INFO_ACTIVATED: 'world_info_activated',
|
||||
TEXT_COMPLETION_SETTINGS_READY: 'text_completion_settings_ready',
|
||||
CHAT_COMPLETION_SETTINGS_READY: 'chat_completion_settings_ready',
|
||||
CHARACTER_FIRST_MESSAGE_SELECTED: 'character_first_message_selected',
|
||||
// TODO: Naming convention is inconsistent with other events
|
||||
CHARACTER_DELETED: 'characterDeleted',
|
||||
@ -7566,6 +7567,7 @@ window['SillyTavern'].getContext = function () {
|
||||
getCurrentChatId: getCurrentChatId,
|
||||
getRequestHeaders: getRequestHeaders,
|
||||
reloadCurrentChat: reloadCurrentChat,
|
||||
renameChat: renameChat,
|
||||
saveSettingsDebounced: saveSettingsDebounced,
|
||||
onlineStatus: online_status,
|
||||
maxContext: Number(max_context),
|
||||
@ -8288,6 +8290,58 @@ async function doDeleteChat() {
|
||||
$('#dialogue_popup_ok').trigger('click', { fromSlashCommand: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Renames the currently selected chat.
|
||||
* @param {string} oldFileName Old name of the chat (no JSONL extension)
|
||||
* @param {string} newName New name for the chat (no JSONL extension)
|
||||
*/
|
||||
export async function renameChat(oldFileName, newName) {
|
||||
const body = {
|
||||
is_group: !!selected_group,
|
||||
avatar_url: characters[this_chid]?.avatar,
|
||||
original_file: `${oldFileName}.jsonl`,
|
||||
renamed_file: `${newName}.jsonl`,
|
||||
};
|
||||
|
||||
try {
|
||||
showLoader();
|
||||
const response = await fetch('/api/chats/rename', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
headers: getRequestHeaders(),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Unsuccessful request.');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
throw new Error('Server returned an error.');
|
||||
}
|
||||
|
||||
if (selected_group) {
|
||||
await renameGroupChat(selected_group, oldFileName, newName);
|
||||
}
|
||||
else {
|
||||
if (characters[this_chid].chat == oldFileName) {
|
||||
characters[this_chid].chat = newName;
|
||||
$('#selected_chat_pole').val(characters[this_chid].chat);
|
||||
await createOrEditCharacter();
|
||||
}
|
||||
}
|
||||
|
||||
await reloadCurrentChat();
|
||||
} catch {
|
||||
hideLoader();
|
||||
await delay(500);
|
||||
await callPopup('An error has occurred. Chat was not renamed.', 'text');
|
||||
} finally {
|
||||
hideLoader();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* /getchatname` slash command
|
||||
*/
|
||||
@ -8966,69 +9020,26 @@ jQuery(async function () {
|
||||
|
||||
$(document).on('click', '.renameChatButton', async function (e) {
|
||||
e.stopPropagation();
|
||||
const old_filenamefull = $(this).closest('.select_chat_block_wrapper').find('.select_chat_block_filename').text();
|
||||
const old_filename = old_filenamefull.replace('.jsonl', '');
|
||||
const oldFileNameFull = $(this).closest('.select_chat_block_wrapper').find('.select_chat_block_filename').text();
|
||||
const oldFileName = oldFileNameFull.replace('.jsonl', '');
|
||||
|
||||
const popupText = `<h3>Enter the new name for the chat:<h3>
|
||||
<small>!!Using an existing filename will produce an error!!<br>
|
||||
This will break the link between checkpoint chats.<br>
|
||||
No need to add '.jsonl' at the end.<br>
|
||||
</small>`;
|
||||
const newName = await callPopup(popupText, 'input', old_filename);
|
||||
const newName = await callPopup(popupText, 'input', oldFileName);
|
||||
|
||||
if (!newName || newName == old_filename) {
|
||||
if (!newName || newName == oldFileName) {
|
||||
console.log('no new name found, aborting');
|
||||
return;
|
||||
}
|
||||
|
||||
const body = {
|
||||
is_group: !!selected_group,
|
||||
avatar_url: characters[this_chid]?.avatar,
|
||||
original_file: `${old_filename}.jsonl`,
|
||||
renamed_file: `${newName}.jsonl`,
|
||||
};
|
||||
await renameChat(oldFileName, newName);
|
||||
|
||||
try {
|
||||
showLoader();
|
||||
const response = await fetch('/api/chats/rename', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(body),
|
||||
headers: getRequestHeaders(),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Unsuccessful request.');
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
throw new Error('Server returned an error.');
|
||||
}
|
||||
|
||||
if (selected_group) {
|
||||
await renameGroupChat(selected_group, old_filename, newName);
|
||||
}
|
||||
else {
|
||||
if (characters[this_chid].chat == old_filename) {
|
||||
characters[this_chid].chat = newName;
|
||||
$('#selected_chat_pole').val(characters[this_chid].chat);
|
||||
await createOrEditCharacter();
|
||||
}
|
||||
}
|
||||
|
||||
await reloadCurrentChat();
|
||||
|
||||
await delay(250);
|
||||
$('#option_select_chat').trigger('click');
|
||||
$('#options').hide();
|
||||
} catch {
|
||||
hideLoader();
|
||||
await delay(500);
|
||||
await callPopup('An error has occurred. Chat was not renamed.', 'text');
|
||||
} finally {
|
||||
hideLoader();
|
||||
}
|
||||
await delay(250);
|
||||
$('#option_select_chat').trigger('click');
|
||||
$('#options').hide();
|
||||
});
|
||||
|
||||
$(document).on('click', '.exportChatButton, .exportRawChatButton', async function (e) {
|
||||
|
@ -1133,6 +1133,11 @@ export function initRossMods() {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($('#dialogue_del_mes_cancel').is(':visible')) {
|
||||
$('#dialogue_del_mes_cancel').trigger('click');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($('.drawer-content')
|
||||
.not('#WorldInfo')
|
||||
.not('#left-nav-panel')
|
||||
|
@ -24,6 +24,7 @@
|
||||
* @property {boolean} group_override - Overrides any existing group assignment for the extension.
|
||||
* @property {number} group_weight - A value used for prioritizing extensions within the same group.
|
||||
* @property {boolean} prevent_recursion - Completely disallows recursive application of the extension.
|
||||
* @property {boolean} delay_until_recursion - Will only be checked during recursion.
|
||||
* @property {number} scan_depth - The maximum depth to search for matches when applying the extension.
|
||||
* @property {boolean} match_whole_words - Specifies if only entire words should be matched during extension application.
|
||||
* @property {boolean} use_group_scoring - Indicates if group weight is considered when selecting extensions.
|
||||
|
@ -1847,6 +1847,8 @@ async function sendOpenAIRequest(type, messages, signal) {
|
||||
generate_data['seed'] = oai_settings.seed;
|
||||
}
|
||||
|
||||
await eventSource.emit(event_types.CHAT_COMPLETION_SETTINGS_READY, generate_data);
|
||||
|
||||
const generate_url = '/api/backends/chat-completions/generate';
|
||||
const response = await fetch(generate_url, {
|
||||
method: 'POST',
|
||||
|
@ -50,6 +50,14 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult {
|
||||
}
|
||||
|
||||
getNamedArgumentAt(text, index, isSelect) {
|
||||
function getSplitRegex() {
|
||||
try {
|
||||
return new RegExp('(?<==)');
|
||||
} catch {
|
||||
// For browsers that don't support lookbehind
|
||||
return new RegExp('=(.*)');
|
||||
}
|
||||
}
|
||||
const notProvidedNamedArguments = this.executor.command.namedArgumentList.filter(arg=>!this.executor.namedArgumentList.find(it=>it.name == arg.name));
|
||||
let name;
|
||||
let value;
|
||||
@ -62,7 +70,7 @@ export class SlashCommandAutoCompleteNameResult extends AutoCompleteNameResult {
|
||||
// cursor is somewhere within the named arguments (including final space)
|
||||
argAssign = this.executor.namedArgumentList.find(it=>it.start <= index && it.end >= index);
|
||||
if (argAssign) {
|
||||
const [argName, ...v] = text.slice(argAssign.start, index).split(/(?<==)/);
|
||||
const [argName, ...v] = text.slice(argAssign.start, index).split(getSplitRegex());
|
||||
name = argName;
|
||||
value = v.join('');
|
||||
start = argAssign.start;
|
||||
|
@ -186,6 +186,15 @@ export class SlashCommandParser {
|
||||
relevance: 0,
|
||||
};
|
||||
|
||||
function getQuotedRunRegex() {
|
||||
try {
|
||||
return new RegExp('(".+?(?<!\\\\)")|(\\S+?)');
|
||||
} catch {
|
||||
// fallback for browsers that don't support lookbehind
|
||||
return /(".+?")|(\S+?)/;
|
||||
}
|
||||
}
|
||||
|
||||
const COMMENT = {
|
||||
scope: 'comment',
|
||||
begin: /\/[/#]/,
|
||||
@ -225,7 +234,7 @@ export class SlashCommandParser {
|
||||
const RUN = {
|
||||
match: [
|
||||
/\/:/,
|
||||
/(".+?(?<!\\)") |(\S+?) /,
|
||||
getQuotedRunRegex(),
|
||||
],
|
||||
className: {
|
||||
1: 'variable.language',
|
||||
|
@ -1276,6 +1276,7 @@ const originalDataKeyMap = {
|
||||
'displayIndex': 'extensions.display_index',
|
||||
'excludeRecursion': 'extensions.exclude_recursion',
|
||||
'preventRecursion': 'extensions.prevent_recursion',
|
||||
'delayUntilRecursion': 'extensions.delay_until_recursion',
|
||||
'selectiveLogic': 'selectiveLogic',
|
||||
'comment': 'comment',
|
||||
'constant': 'constant',
|
||||
@ -1361,7 +1362,7 @@ function splitKeywordsAndRegexes(input) {
|
||||
// No need for validation here
|
||||
const addFindCallback = (/** @type {Select2Option} */ item) => {
|
||||
keywordsAndRegexes.push(item.text);
|
||||
}
|
||||
};
|
||||
|
||||
const { term } = customTokenizer({ _type: 'custom_call', term: input }, undefined, addFindCallback);
|
||||
const finalTerm = term.trim();
|
||||
@ -1501,7 +1502,7 @@ function getWorldEntry(name, data, entry) {
|
||||
const isRegex = isValidRegex(item.text);
|
||||
if (isRegex) {
|
||||
content.html(highlightRegex(item.text));
|
||||
content.addClass('regex_item').prepend($('<span>').addClass('regex_icon').text("•*").attr('title', 'Regex'));
|
||||
content.addClass('regex_item').prepend($('<span>').addClass('regex_icon').text('•*').attr('title', 'Regex'));
|
||||
}
|
||||
|
||||
if (searchStyle && item.count) {
|
||||
@ -1551,7 +1552,7 @@ function getWorldEntry(name, data, entry) {
|
||||
if (index > -1) selected.splice(index, 1);
|
||||
input.val(selected).trigger('change');
|
||||
// Manually update the cache, that change event is not gonna trigger it
|
||||
updateWorldEntryKeyOptionsCache([key], { remove: true })
|
||||
updateWorldEntryKeyOptionsCache([key], { remove: true });
|
||||
|
||||
// We need to "hack" the actual text input into the currently open textarea
|
||||
input.next('span.select2-container').find('textarea')
|
||||
@ -1580,10 +1581,10 @@ function getWorldEntry(name, data, entry) {
|
||||
}
|
||||
|
||||
// key
|
||||
enableKeysInput("key", "keys");
|
||||
enableKeysInput('key', 'keys');
|
||||
|
||||
// keysecondary
|
||||
enableKeysInput("keysecondary", "secondary_keys");
|
||||
enableKeysInput('keysecondary', 'secondary_keys');
|
||||
|
||||
// draw key input switch button
|
||||
template.find('.switch_input_type_icon').on('click', function () {
|
||||
@ -1871,7 +1872,7 @@ function getWorldEntry(name, data, entry) {
|
||||
saveWorldInfo(name, data);
|
||||
});
|
||||
groupInput.val(entry.group ?? '').trigger('input');
|
||||
setTimeout(() => createEntryInputAutocomplete(groupInput, getInclusionGroupCallback(data)), 1);
|
||||
setTimeout(() => createEntryInputAutocomplete(groupInput, getInclusionGroupCallback(data), { allowMultiple: true }), 1);
|
||||
|
||||
// inclusion priority
|
||||
const groupOverrideInput = template.find('input[name="groupOverride"]');
|
||||
@ -2143,6 +2144,18 @@ function getWorldEntry(name, data, entry) {
|
||||
});
|
||||
preventRecursionInput.prop('checked', entry.preventRecursion).trigger('input');
|
||||
|
||||
// delay until recursion
|
||||
const delayUntilRecursionInput = template.find('input[name="delay_until_recursion"]');
|
||||
delayUntilRecursionInput.data('uid', entry.uid);
|
||||
delayUntilRecursionInput.on('input', function () {
|
||||
const uid = $(this).data('uid');
|
||||
const value = $(this).prop('checked');
|
||||
data.entries[uid].delayUntilRecursion = value;
|
||||
setOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion);
|
||||
saveWorldInfo(name, data);
|
||||
});
|
||||
delayUntilRecursionInput.prop('checked', entry.delayUntilRecursion).trigger('input');
|
||||
|
||||
// duplicate button
|
||||
const duplicateButton = template.find('.duplicate_entry_button');
|
||||
duplicateButton.data('uid', entry.uid);
|
||||
@ -2281,11 +2294,15 @@ function getWorldEntry(name, data, entry) {
|
||||
* @returns {(input: any, output: any) => any} Callback function for the autocomplete
|
||||
*/
|
||||
function getInclusionGroupCallback(data) {
|
||||
return function (input, output) {
|
||||
return function (control, input, output) {
|
||||
const uid = $(control).data('uid');
|
||||
const thisGroups = String($(control).val()).split(/,\s*/).filter(x => x).map(x => x.toLowerCase());
|
||||
const groups = new Set();
|
||||
for (const entry of Object.values(data.entries)) {
|
||||
// Skip the groups of this entry, because auto-complete should only suggest the ones that are already available on other entries
|
||||
if (entry.uid == uid) continue;
|
||||
if (entry.group) {
|
||||
groups.add(String(entry.group));
|
||||
entry.group.split(/,\s*/).filter(x => x).forEach(x => groups.add(x));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2293,20 +2310,19 @@ function getInclusionGroupCallback(data) {
|
||||
haystack.sort((a, b) => a.localeCompare(b));
|
||||
const needle = input.term.toLowerCase();
|
||||
const hasExactMatch = haystack.findIndex(x => x.toLowerCase() == needle) !== -1;
|
||||
const result = haystack.filter(x => x.toLowerCase().includes(needle));
|
||||
|
||||
if (input.term && !hasExactMatch) {
|
||||
result.unshift(input.term);
|
||||
}
|
||||
const result = haystack.filter(x => x.toLowerCase().includes(needle) && (!thisGroups.includes(x) || hasExactMatch && thisGroups.filter(g => g == x).length == 1));
|
||||
|
||||
output(result);
|
||||
};
|
||||
}
|
||||
|
||||
function getAutomationIdCallback(data) {
|
||||
return function (input, output) {
|
||||
return function (control, input, output) {
|
||||
const uid = $(control).data('uid');
|
||||
const ids = new Set();
|
||||
for (const entry of Object.values(data.entries)) {
|
||||
// Skip automation id of this entry, because auto-complete should only suggest the ones that are already available on other entries
|
||||
if (entry.uid == uid) continue;
|
||||
if (entry.automationId) {
|
||||
ids.add(String(entry.automationId));
|
||||
}
|
||||
@ -2322,36 +2338,53 @@ function getAutomationIdCallback(data) {
|
||||
const haystack = Array.from(ids);
|
||||
haystack.sort((a, b) => a.localeCompare(b));
|
||||
const needle = input.term.toLowerCase();
|
||||
const hasExactMatch = haystack.findIndex(x => x.toLowerCase() == needle) !== -1;
|
||||
const result = haystack.filter(x => x.toLowerCase().includes(needle));
|
||||
|
||||
if (input.term && !hasExactMatch) {
|
||||
result.unshift(input.term);
|
||||
}
|
||||
|
||||
output(result);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an autocomplete for the inclusion group.
|
||||
* @param {JQuery<HTMLElement>} input Input element to attach the autocomplete to
|
||||
* @param {(input: any, output: any) => any} callback Source data callbacks
|
||||
* @param {JQuery<HTMLElement>} input - Input element to attach the autocomplete to
|
||||
* @param {(control: JQuery<HTMLElement>, input: any, output: any) => any} callback - Source data callbacks
|
||||
* @param {object} [options={}] - Optional arguments
|
||||
* @param {boolean} [options.allowMultiple=false] - Whether to allow multiple comma-separated values
|
||||
*/
|
||||
function createEntryInputAutocomplete(input, callback) {
|
||||
function createEntryInputAutocomplete(input, callback, { allowMultiple = false } = {}) {
|
||||
const handleSelect = (event, ui) => {
|
||||
// Prevent default autocomplete select, so we can manually set the value
|
||||
event.preventDefault();
|
||||
if (!allowMultiple) {
|
||||
$(input).val(ui.item.value).trigger('input').trigger('blur');
|
||||
} else {
|
||||
var terms = String($(input).val()).split(/,\s*/);
|
||||
terms.pop(); // remove the current input
|
||||
terms.push(ui.item.value); // add the selected item
|
||||
$(input).val(terms.filter(x => x).join(', ')).trigger('input').trigger('blur');
|
||||
}
|
||||
};
|
||||
|
||||
$(input).autocomplete({
|
||||
minLength: 0,
|
||||
source: callback,
|
||||
select: function (_event, ui) {
|
||||
$(input).val(ui.item.value).trigger('input').trigger('blur');
|
||||
source: function (request, response) {
|
||||
if (!allowMultiple) {
|
||||
callback(input, request, response);
|
||||
} else {
|
||||
const term = request.term.split(/,\s*/).pop();
|
||||
request.term = term;
|
||||
callback(input, request, response);
|
||||
}
|
||||
},
|
||||
select: handleSelect,
|
||||
});
|
||||
|
||||
$(input).on('focus click', function () {
|
||||
$(input).autocomplete('search', String($(input).val()));
|
||||
$(input).autocomplete('search', allowMultiple ? String($(input).val()).split(/,\s*/).pop() : $(input).val());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Duplicated a WI entry by copying all of its properties and assigning a new uid
|
||||
* @param {*} data - The data of the book
|
||||
@ -2404,6 +2437,8 @@ const newEntryTemplate = {
|
||||
position: 0,
|
||||
disable: false,
|
||||
excludeRecursion: false,
|
||||
preventRecursion: false,
|
||||
delayUntilRecursion: false,
|
||||
probability: 100,
|
||||
useProbability: true,
|
||||
depth: DEFAULT_DEPTH,
|
||||
@ -2771,7 +2806,7 @@ async function checkWorldInfo(chat, maxContext) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (allActivatedEntries.has(entry) || entry.disable == true || (count > 1 && world_info_recursive && entry.excludeRecursion)) {
|
||||
if (allActivatedEntries.has(entry) || entry.disable == true || (count > 1 && world_info_recursive && entry.excludeRecursion) || (count == 1 && entry.delayUntilRecursion)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3044,10 +3079,12 @@ function filterGroupsByScoring(groups, buffer, removeEntry) {
|
||||
function filterByInclusionGroups(newEntries, allActivatedEntries, buffer) {
|
||||
console.debug('-- INCLUSION GROUP CHECKS BEGIN --');
|
||||
const grouped = newEntries.filter(x => x.group).reduce((acc, item) => {
|
||||
if (!acc[item.group]) {
|
||||
acc[item.group] = [];
|
||||
}
|
||||
acc[item.group].push(item);
|
||||
item.group.split(/,\s*/).filter(x => x).forEach(group => {
|
||||
if (!acc[group]) {
|
||||
acc[group] = [];
|
||||
}
|
||||
acc[group].push(item);
|
||||
});
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
@ -3139,6 +3176,7 @@ function convertAgnaiMemoryBook(inputObj) {
|
||||
disable: !entry.enabled,
|
||||
addMemo: !!entry.name,
|
||||
excludeRecursion: false,
|
||||
delayUntilRecursion: false,
|
||||
displayIndex: index,
|
||||
probability: 100,
|
||||
useProbability: true,
|
||||
@ -3177,6 +3215,7 @@ function convertRisuLorebook(inputObj) {
|
||||
disable: false,
|
||||
addMemo: true,
|
||||
excludeRecursion: false,
|
||||
delayUntilRecursion: false,
|
||||
displayIndex: index,
|
||||
probability: entry.activationPercent ?? 100,
|
||||
useProbability: entry.activationPercent ?? true,
|
||||
@ -3220,6 +3259,7 @@ function convertNovelLorebook(inputObj) {
|
||||
disable: !entry.enabled,
|
||||
addMemo: addMemo,
|
||||
excludeRecursion: false,
|
||||
delayUntilRecursion: false,
|
||||
displayIndex: index,
|
||||
probability: 100,
|
||||
useProbability: true,
|
||||
@ -3260,6 +3300,7 @@ function convertCharacterBook(characterBook) {
|
||||
position: entry.extensions?.position ?? (entry.position === 'before_char' ? world_info_position.before : world_info_position.after),
|
||||
excludeRecursion: entry.extensions?.exclude_recursion ?? false,
|
||||
preventRecursion: entry.extensions?.prevent_recursion ?? false,
|
||||
delayUntilRecursion: entry.extensions?.delay_until_recursion ?? false,
|
||||
disable: !entry.enabled,
|
||||
addMemo: entry.comment ? true : false,
|
||||
displayIndex: entry.extensions?.display_index ?? index,
|
||||
|
@ -129,7 +129,7 @@ body {
|
||||
height: 100vh;
|
||||
height: 100svh;
|
||||
/*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/
|
||||
height: calc(var(--doc-height) - 1px);
|
||||
/*height: calc(var(--doc-height) - 1px);*/
|
||||
background-color: var(--greyCAIbg);
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
@ -872,7 +872,8 @@ body .panelControlBar {
|
||||
}
|
||||
|
||||
#chat .mes.selected{
|
||||
background-color: rgb(from var(--SmartThemeQuoteColor) r g b / .5);
|
||||
/* background-color: rgb(from var(--SmartThemeQuoteColor) r g b / .5); */
|
||||
background-color: rgb(102, 0, 0);
|
||||
}
|
||||
|
||||
.mes q:before,
|
||||
|
@ -436,6 +436,7 @@ function convertWorldInfoToCharacterBook(name, entries) {
|
||||
group_override: entry.groupOverride ?? false,
|
||||
group_weight: entry.groupWeight ?? null,
|
||||
prevent_recursion: entry.preventRecursion ?? false,
|
||||
delay_until_recursion: entry.delayUntilRecursion ?? false,
|
||||
scan_depth: entry.scanDepth ?? null,
|
||||
match_whole_words: entry.matchWholeWords ?? null,
|
||||
use_group_scoring: entry.useGroupScoring ?? false,
|
||||
|
@ -2,7 +2,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
const express = require('express');
|
||||
const { SentencePieceProcessor } = require('@agnai/sentencepiece-js');
|
||||
const tiktoken = require('@dqbd/tiktoken');
|
||||
const tiktoken = require('tiktoken');
|
||||
const { Tokenizer } = require('@agnai/web-tokenizers');
|
||||
const { convertClaudePrompt, convertGooglePrompt } = require('../prompt-converters');
|
||||
const { readSecret, SECRET_KEYS } = require('./secrets');
|
||||
@ -15,7 +15,7 @@ const { setAdditionalHeaders } = require('../additional-headers');
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {{[key: string]: import("@dqbd/tiktoken").Tiktoken}} Tokenizers cache
|
||||
* @type {{[key: string]: import('tiktoken').Tiktoken}} Tokenizers cache
|
||||
*/
|
||||
const tokenizersCache = {};
|
||||
|
||||
@ -262,6 +262,10 @@ function getWebTokenizersChunks(tokenizer, ids) {
|
||||
* @returns {string} Tokenizer model to use
|
||||
*/
|
||||
function getTokenizerModel(requestModel) {
|
||||
if (requestModel.includes('gpt-4o')) {
|
||||
return 'gpt-4o';
|
||||
}
|
||||
|
||||
if (requestModel.includes('gpt-4-32k')) {
|
||||
return 'gpt-4-32k';
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user