mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-03-16 03:50:10 +01:00
Merge pull request #2512 from kwaroran/ccv3-write
CCv3 Partial Implementation
This commit is contained in:
commit
623cab0fa5
@ -464,6 +464,7 @@ export function evaluateMacros(content, env) {
|
||||
content = content.replace(/{{firstIncludedMessageId}}/gi, () => String(getFirstIncludedMessageId() ?? ''));
|
||||
content = content.replace(/{{lastSwipeId}}/gi, () => String(getLastSwipeId() ?? ''));
|
||||
content = content.replace(/{{currentSwipeId}}/gi, () => String(getCurrentSwipeId() ?? ''));
|
||||
content = content.replace(/{{reverse\:(.+?)}}/gi, (_, str) => Array.from(str).reverse().join(''));
|
||||
|
||||
content = content.replace(/\{\{\/\/([\s\S]*?)\}\}/gm, '');
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
<li><tt>{{firstIncludedMessageId}}</tt> – <span data-i18n="help_macros_22">the ID of the first message included in the context. Requires generation to be ran at least once in the current session.</span></li>
|
||||
<li><tt>{{currentSwipeId}}</tt> – <span data-i18n="help_macros_23">the 1-based ID of the current swipe in the last chat message. Empty string if the last message is user or prompt-hidden.</span></li>
|
||||
<li><tt>{{lastSwipeId}}</tt> – <span data-i18n="help_macros_24">the number of swipes in the last chat message. Empty string if the last message is user or prompt-hidden.</span></li>
|
||||
<li><tt>{{reverse:(content)}}</tt> – <span data-i18n="help_macros_reverse">reverses the content of the macro.</span></li>
|
||||
<li><tt>{{// (note)}}</tt> – <span data-i18n="help_macros_25">you can leave a note here, and the macro will be replaced with blank content. Not visible for the AI.</span></li>
|
||||
<li><tt>{{time}}</tt> – <span data-i18n="help_macros_26">the current time</span></li>
|
||||
<li><tt>{{date}}</tt> – <span data-i18n="help_macros_27">the current date</span></li>
|
||||
|
@ -107,6 +107,7 @@ const METADATA_KEY = 'world_info';
|
||||
const DEFAULT_DEPTH = 4;
|
||||
const DEFAULT_WEIGHT = 100;
|
||||
const MAX_SCAN_DEPTH = 1000;
|
||||
const KNOWN_DECORATORS = ['@@activate', '@@dont_activate'];
|
||||
|
||||
// Typedef area
|
||||
/**
|
||||
@ -123,6 +124,7 @@ const MAX_SCAN_DEPTH = 1000;
|
||||
* @property {number} [sticky] The sticky value of the entry
|
||||
* @property {number} [cooldown] The cooldown of the entry
|
||||
* @property {number} [delay] The delay of the entry
|
||||
* @property {string[]} [decorators] Array of decorators for the entry
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -3534,6 +3536,12 @@ export async function getSortedEntries() {
|
||||
// Chat lore always goes first
|
||||
entries = [...chatLore.sort(sortFn), ...entries];
|
||||
|
||||
// Parse decorators
|
||||
entries = entries.map((entry) => {
|
||||
const [decorators, content] = parseDecorators(entry.content);
|
||||
return { ...entry, decorators, content };
|
||||
});
|
||||
|
||||
console.debug(`[WI] Found ${entries.length} world lore entries. Sorted by strategy`, Object.entries(world_info_insertion_strategy).find((x) => x[1] === world_info_character_strategy));
|
||||
|
||||
// Need to deep clone the entries to avoid modifying the cached data
|
||||
@ -3545,6 +3553,62 @@ export async function getSortedEntries() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse decorators from worldinfo content
|
||||
* @param {string} content The content to parse
|
||||
* @returns {[string[],string]} The decorators found in the content and the content without decorators
|
||||
*/
|
||||
function parseDecorators(content) {
|
||||
/**
|
||||
* Check if the decorator is known
|
||||
* @param {string} data string to check
|
||||
* @returns {boolean} true if the decorator is known
|
||||
*/
|
||||
const isKnownDecorator = (data) => {
|
||||
if (data.startsWith('@@@')) {
|
||||
data = data.substring(1);
|
||||
}
|
||||
|
||||
for (let i = 0; i < KNOWN_DECORATORS.length; i++) {
|
||||
if (data.startsWith(KNOWN_DECORATORS[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (content.startsWith('@@')) {
|
||||
let newContent = content;
|
||||
const splited = content.split('\n');
|
||||
let decorators = [];
|
||||
let fallbacked = false;
|
||||
|
||||
for (let i = 0; i < splited.length; i++) {
|
||||
if (splited[i].startsWith('@@')) {
|
||||
if (splited[i].startsWith('@@@') && !fallbacked) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isKnownDecorator(splited[i])) {
|
||||
decorators.push(splited[i].startsWith('@@@') ? splited[i].substring(1) : splited[i]);
|
||||
fallbacked = false;
|
||||
}
|
||||
else {
|
||||
fallbacked = true;
|
||||
}
|
||||
} else {
|
||||
newContent = splited.slice(i).join('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [decorators, newContent];
|
||||
}
|
||||
|
||||
return [[], content];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a scan on the chat and returns the world info activated.
|
||||
* @param {string[]} chat The chat messages to scan, in reverse order.
|
||||
@ -3686,6 +3750,17 @@ async function checkWorldInfo(chat, maxContext, isDryRun) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.decorators.includes('@@activate')) {
|
||||
log('activated by @@activate decorator');
|
||||
activatedNow.add(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.decorators.includes('@@dont_activate')) {
|
||||
log('suppressed by @@dont_activate decorator');
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now do checks for immediate activations
|
||||
if (entry.constant) {
|
||||
log('activated because of constant');
|
||||
|
@ -23,9 +23,21 @@ const write = (image, data) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Add new chunks before the IEND chunk
|
||||
// Add new v2 chunk before the IEND chunk
|
||||
const base64EncodedData = Buffer.from(data, 'utf8').toString('base64');
|
||||
chunks.splice(-1, 0, PNGtext.encode('chara', base64EncodedData));
|
||||
|
||||
// Try adding v3 chunk before the IEND chunk
|
||||
try {
|
||||
//change v2 format to v3
|
||||
const v3Data = JSON.parse(data);
|
||||
v3Data.spec = 'chara_card_v3';
|
||||
v3Data.spec_version = '3.0';
|
||||
|
||||
const base64EncodedData = Buffer.from(JSON.stringify(v3Data), 'utf8').toString('base64');
|
||||
chunks.splice(-1, 0, PNGtext.encode('ccv3', base64EncodedData));
|
||||
} catch (error) { }
|
||||
|
||||
const newBuffer = Buffer.from(encode(chunks));
|
||||
return newBuffer;
|
||||
};
|
||||
|
@ -408,6 +408,9 @@ function charaFormatData(data, directories) {
|
||||
//_.set(char, 'data.extensions.avatar', 'none');
|
||||
//_.set(char, 'data.extensions.chat', data.ch_name + ' - ' + humanizedISO8601DateTime());
|
||||
|
||||
// V3 fields
|
||||
_.set(char, 'data.group_only_greetings', data.group_only_greetings ?? []);
|
||||
|
||||
if (data.world) {
|
||||
try {
|
||||
const file = readWorldInfoFile(directories, data.world, false);
|
||||
|
Loading…
x
Reference in New Issue
Block a user