Add function to write extension fields to character cards.
This commit is contained in:
parent
c9c6d798d9
commit
6b2374c405
|
@ -151,7 +151,7 @@ import {
|
|||
isValidUrl,
|
||||
} from './scripts/utils.js';
|
||||
|
||||
import { ModuleWorkerWrapper, doDailyExtensionUpdatesCheck, extension_settings, getContext, loadExtensionSettings, renderExtensionTemplate, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js';
|
||||
import { ModuleWorkerWrapper, doDailyExtensionUpdatesCheck, extension_settings, getContext, loadExtensionSettings, renderExtensionTemplate, runGenerationInterceptors, saveMetadataDebounced, writeExtensionField } from './scripts/extensions.js';
|
||||
import { COMMENT_NAME_DEFAULT, executeSlashCommands, getSlashCommandsHelp, processChatSlashCommands, registerSlashCommand } from './scripts/slash-commands.js';
|
||||
import {
|
||||
tag_map,
|
||||
|
@ -7349,6 +7349,7 @@ window['SillyTavern'].getContext = function () {
|
|||
ModuleWorkerWrapper: ModuleWorkerWrapper,
|
||||
getTokenizerModel: getTokenizerModel,
|
||||
generateQuietPrompt: generateQuietPrompt,
|
||||
writeExtensionField: writeExtensionField,
|
||||
tags: tags,
|
||||
tagMap: tag_map,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders, substituteParams, renderTemplate, animation_duration } from '../script.js';
|
||||
import { hideLoader, showLoader } from './loader.js';
|
||||
import { isSubsetOf } from './utils.js';
|
||||
import { isSubsetOf, setValueByPath } from './utils.js';
|
||||
export {
|
||||
getContext,
|
||||
getApiUrl,
|
||||
|
@ -883,6 +883,55 @@ async function runGenerationInterceptors(chat, contextSize) {
|
|||
return aborted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a field to the character's data extensions object.
|
||||
* @param {number} characterId Index in the character array
|
||||
* @param {string} key Field name
|
||||
* @param {any} value Field value
|
||||
* @returns {Promise<void>} When the field is written
|
||||
*/
|
||||
export async function writeExtensionField(characterId, key, value) {
|
||||
const context = getContext();
|
||||
const character = context.characters[characterId];
|
||||
if (!character) {
|
||||
console.warn('Character not found', characterId);
|
||||
return;
|
||||
}
|
||||
const path = `data.extensions.${key}`;
|
||||
setValueByPath(character, path, value);
|
||||
|
||||
// Process JSON data
|
||||
if (character.json_data) {
|
||||
const jsonData = JSON.parse(character.json_data);
|
||||
setValueByPath(jsonData, path, value);
|
||||
character.json_data = JSON.stringify(jsonData);
|
||||
|
||||
// Make sure the data doesn't get lost when saving the current character
|
||||
if (Number(characterId) === Number(context.characterId)) {
|
||||
$('#character_json_data').val(character.json_data);
|
||||
}
|
||||
}
|
||||
|
||||
// Save data to the server
|
||||
const saveDataRequest = {
|
||||
avatar: character.avatar,
|
||||
data: {
|
||||
extensions: {
|
||||
[key]: value,
|
||||
},
|
||||
},
|
||||
};
|
||||
const mergeResponse = await fetch('/api/characters/merge-attributes', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify(saveDataRequest),
|
||||
});
|
||||
|
||||
if (!mergeResponse.ok) {
|
||||
console.error('Failed to save extension field', mergeResponse.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
jQuery(function () {
|
||||
addExtensionsButtonAndMenu();
|
||||
$('#extensionsMenuButton').css('display', 'flex');
|
||||
|
|
|
@ -1226,3 +1226,27 @@ export async function extractTextFromMarkdown(blob) {
|
|||
const text = postProcessText(document.body.textContent, false);
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in an object by a path.
|
||||
* @param {object} obj Object to set value in
|
||||
* @param {string} path Key path
|
||||
* @param {any} value Value to set
|
||||
* @returns {void}
|
||||
*/
|
||||
export function setValueByPath(obj, path, value) {
|
||||
const keyParts = path.split('.');
|
||||
let currentObject = obj;
|
||||
|
||||
for (let i = 0; i < keyParts.length - 1; i++) {
|
||||
const part = keyParts[i];
|
||||
|
||||
if (!Object.hasOwn(currentObject, part)) {
|
||||
currentObject[part] = {};
|
||||
}
|
||||
|
||||
currentObject = currentObject[part];
|
||||
}
|
||||
|
||||
currentObject[keyParts[keyParts.length - 1]] = value;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId } from '../script.js';
|
||||
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean } from './utils.js';
|
||||
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath } from './utils.js';
|
||||
import { extension_settings, getContext } from './extensions.js';
|
||||
import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js';
|
||||
import { registerSlashCommand } from './slash-commands.js';
|
||||
|
@ -950,20 +950,7 @@ function setOriginalDataValue(data, uid, key, value) {
|
|||
return;
|
||||
}
|
||||
|
||||
const keyParts = key.split('.');
|
||||
let currentObject = originalEntry;
|
||||
|
||||
for (let i = 0; i < keyParts.length - 1; i++) {
|
||||
const part = keyParts[i];
|
||||
|
||||
if (!Object.hasOwn(currentObject, part)) {
|
||||
currentObject[part] = {};
|
||||
}
|
||||
|
||||
currentObject = currentObject[part];
|
||||
}
|
||||
|
||||
currentObject[keyParts[keyParts.length - 1]] = value;
|
||||
setValueByPath(originalEntry, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -600,10 +600,10 @@ router.post('/edit-attribute', jsonParser, async function (request, response) {
|
|||
* @returns {void}
|
||||
* */
|
||||
router.post('/merge-attributes', jsonParser, async function (request, response) {
|
||||
const update = request.body;
|
||||
const avatarPath = path.join(DIRECTORIES.characters, update.avatar);
|
||||
|
||||
try {
|
||||
const update = request.body;
|
||||
const avatarPath = path.join(DIRECTORIES.characters, update.avatar);
|
||||
|
||||
const pngStringData = await charaRead(avatarPath);
|
||||
|
||||
if (!pngStringData) {
|
||||
|
|
Loading…
Reference in New Issue