mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add function to write extension fields to character cards.
This commit is contained in:
@ -151,7 +151,7 @@ import {
|
|||||||
isValidUrl,
|
isValidUrl,
|
||||||
} from './scripts/utils.js';
|
} 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 { COMMENT_NAME_DEFAULT, executeSlashCommands, getSlashCommandsHelp, processChatSlashCommands, registerSlashCommand } from './scripts/slash-commands.js';
|
||||||
import {
|
import {
|
||||||
tag_map,
|
tag_map,
|
||||||
@ -7349,6 +7349,7 @@ window['SillyTavern'].getContext = function () {
|
|||||||
ModuleWorkerWrapper: ModuleWorkerWrapper,
|
ModuleWorkerWrapper: ModuleWorkerWrapper,
|
||||||
getTokenizerModel: getTokenizerModel,
|
getTokenizerModel: getTokenizerModel,
|
||||||
generateQuietPrompt: generateQuietPrompt,
|
generateQuietPrompt: generateQuietPrompt,
|
||||||
|
writeExtensionField: writeExtensionField,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
tagMap: tag_map,
|
tagMap: tag_map,
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders, substituteParams, renderTemplate, animation_duration } from '../script.js';
|
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders, substituteParams, renderTemplate, animation_duration } from '../script.js';
|
||||||
import { hideLoader, showLoader } from './loader.js';
|
import { hideLoader, showLoader } from './loader.js';
|
||||||
import { isSubsetOf } from './utils.js';
|
import { isSubsetOf, setValueByPath } from './utils.js';
|
||||||
export {
|
export {
|
||||||
getContext,
|
getContext,
|
||||||
getApiUrl,
|
getApiUrl,
|
||||||
@ -883,6 +883,55 @@ async function runGenerationInterceptors(chat, contextSize) {
|
|||||||
return aborted;
|
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 () {
|
jQuery(function () {
|
||||||
addExtensionsButtonAndMenu();
|
addExtensionsButtonAndMenu();
|
||||||
$('#extensionsMenuButton').css('display', 'flex');
|
$('#extensionsMenuButton').css('display', 'flex');
|
||||||
|
@ -1226,3 +1226,27 @@ export async function extractTextFromMarkdown(blob) {
|
|||||||
const text = postProcessText(document.body.textContent, false);
|
const text = postProcessText(document.body.textContent, false);
|
||||||
return text;
|
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 { 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 { extension_settings, getContext } from './extensions.js';
|
||||||
import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js';
|
import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js';
|
||||||
import { registerSlashCommand } from './slash-commands.js';
|
import { registerSlashCommand } from './slash-commands.js';
|
||||||
@ -950,20 +950,7 @@ function setOriginalDataValue(data, uid, key, value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyParts = key.split('.');
|
setValueByPath(originalEntry, key, value);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,10 +600,10 @@ router.post('/edit-attribute', jsonParser, async function (request, response) {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
* */
|
* */
|
||||||
router.post('/merge-attributes', jsonParser, async function (request, response) {
|
router.post('/merge-attributes', jsonParser, async function (request, response) {
|
||||||
|
try {
|
||||||
const update = request.body;
|
const update = request.body;
|
||||||
const avatarPath = path.join(DIRECTORIES.characters, update.avatar);
|
const avatarPath = path.join(DIRECTORIES.characters, update.avatar);
|
||||||
|
|
||||||
try {
|
|
||||||
const pngStringData = await charaRead(avatarPath);
|
const pngStringData = await charaRead(avatarPath);
|
||||||
|
|
||||||
if (!pngStringData) {
|
if (!pngStringData) {
|
||||||
|
Reference in New Issue
Block a user