mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Prototyping
This commit is contained in:
22
src/util.js
22
src/util.js
@@ -196,6 +196,27 @@ async function readAllChunks(readableStream) {
|
||||
});
|
||||
}
|
||||
|
||||
function isObject(item) {
|
||||
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||
}
|
||||
|
||||
function deepMerge(target, source) {
|
||||
let output = Object.assign({}, target);
|
||||
if (isObject(target) && isObject(source)) {
|
||||
Object.keys(source).forEach(key => {
|
||||
if (isObject(source[key])) {
|
||||
if (!(key in target))
|
||||
Object.assign(output, { [key]: source[key] });
|
||||
else
|
||||
output[key] = deepMerge(target[key], source[key]);
|
||||
} else {
|
||||
Object.assign(output, { [key]: source[key] });
|
||||
}
|
||||
});
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getConfig,
|
||||
getConfigValue,
|
||||
@@ -205,4 +226,5 @@ module.exports = {
|
||||
getImageBuffers,
|
||||
readAllChunks,
|
||||
delay,
|
||||
deepMerge,
|
||||
};
|
||||
|
129
src/validator/TavernCardValidator.js
Normal file
129
src/validator/TavernCardValidator.js
Normal file
@@ -0,0 +1,129 @@
|
||||
const characterBook = require("lodash/object");
|
||||
|
||||
/**
|
||||
* Validates the data structure of character cards.
|
||||
* Supported specs: V1, V2
|
||||
* Up to: 8083fb3
|
||||
*
|
||||
* @link https://github.com/malfoyslastname/character-card-spec-v2
|
||||
*/
|
||||
class TavernCardValidator {
|
||||
#validationError = null;
|
||||
|
||||
constructor(card) {
|
||||
this.card = card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field that caused the validation to fail
|
||||
*
|
||||
* @returns {null|string}
|
||||
*/
|
||||
get validationError() {
|
||||
return this.#validationError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate against V1 and V2 spec.
|
||||
*
|
||||
* @returns {number|boolean} - false when neither V1 nor V2 spec were matched. Specification version number otherwise.
|
||||
*/
|
||||
validate() {
|
||||
this.#validationError = null;
|
||||
|
||||
if (this.validateV1()) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (this.validateV2()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate against V1 specification
|
||||
*
|
||||
* @returns {this is string[]}
|
||||
*/
|
||||
validateV1() {
|
||||
const requiredFields = ['name', 'description', 'personality', 'scenario', 'first_mes', 'mes_example'];
|
||||
return requiredFields.every(field => {
|
||||
if (!this.card.hasOwnProperty(field)) {
|
||||
this.#validationError = field;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate against V2 specification
|
||||
*
|
||||
* @returns {false|boolean|*}
|
||||
*/
|
||||
validateV2() {
|
||||
return this.#validateSpec()
|
||||
&& this.#validateSpecVersion()
|
||||
&& this.#validateData()
|
||||
&& this.#validateCharacterBook();
|
||||
}
|
||||
|
||||
#validateSpec() {
|
||||
if (this.card.spec !== 'chara_card_v2') {
|
||||
this.#validationError = 'spec';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#validateSpecVersion() {
|
||||
if (this.card.spec_version !== '2.0') {
|
||||
this.#validationError = 'spec_version';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#validateData() {
|
||||
const data = this.card.data;
|
||||
|
||||
if (!data) {
|
||||
this.#validationError = 'data';
|
||||
return false;
|
||||
}
|
||||
|
||||
const requiredFields = ['name', 'description', 'personality', 'scenario', 'first_mes', 'mes_example', 'creator_notes', 'system_prompt', 'post_history_instructions', 'alternate_greetings', 'tags', 'creator', 'character_version', 'extensions'];
|
||||
const isAllRequiredFieldsPresent = requiredFields.every(field => {
|
||||
if (!data.hasOwnProperty(field)) {
|
||||
this.#validationError = `data.${field}`;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return isAllRequiredFieldsPresent && Array.isArray(data.alternate_greetings) && Array.isArray(data.tags) && typeof data.extensions === 'object';
|
||||
}
|
||||
|
||||
#validateCharacterBook() {
|
||||
const characterBook = this.card.data.character_book;
|
||||
|
||||
if (!characterBook) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const requiredFields = ['extensions', 'entries'];
|
||||
const isAllRequiredFieldsPresent = requiredFields.every(field => {
|
||||
if (!characterBook.hasOwnProperty(field)) {
|
||||
this.#validationError = `data.character_book.${field}`;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return isAllRequiredFieldsPresent && Array.isArray(characterBook.entries) && typeof characterBook.extensions === 'object';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {TavernCardValidator}
|
Reference in New Issue
Block a user