Isolate result type / class

This commit is contained in:
DominikDoom
2025-07-12 18:39:06 +02:00
parent 781cea83a0
commit 8a574ec5e1
11 changed files with 60 additions and 60 deletions

View File

@@ -1,7 +1,7 @@
// Result data type for cleaner use of optional completion result properties
// Type enum
const ResultType = Object.freeze({
TAC.ResultType = Object.freeze({
"tag": 1,
"extra": 2,
"embedding": 3,
@@ -17,10 +17,10 @@ const ResultType = Object.freeze({
});
// Class to hold result data and annotations to make it clearer to use
class AutocompleteResult {
TAC.AutocompleteResult = class AutocompleteResult {
// Main properties
text = "";
type = ResultType.tag;
type = TAC.ResultType.tag;
// Additional info, only used in some cases
category = null;

View File

@@ -252,7 +252,7 @@ class TacUtils {
/**
* Calculate biased tag score based on post count and frequent usage
* @param {AutocompleteResult} result - The unbiased result
* @param {TAC.AutocompleteResult} result - The unbiased result
* @param {Number} count - The post count (or similar base metric)
* @param {Number} uses - The usage count
* @returns {Number} The biased score for sorting
@@ -305,7 +305,7 @@ class TacUtils {
* Calls API endpoint to increase the count of a tag in the database.
* Not awaited as it is non-critical and can be executed as fire-and-forget.
* @param {String} tagName - The name of the tag
* @param {ResultType} type - The type of the tag as mapped in {@link ResultType}
* @param {TAC.ResultType} type - The type of the tag as mapped in {@link TAC.ResultType}
* @param {Boolean} negative - Whether the tag was typed in a negative prompt field
*/
static increaseUseCount(tagName, type, negative = false) {
@@ -315,7 +315,7 @@ class TacUtils {
/**
* Get the use count of a tag from the database
* @param {String} tagName - The name of the tag
* @param {ResultType} type - The type of the tag as mapped in {@link ResultType}
* @param {TAC.ResultType} type - The type of the tag as mapped in {@link TAC.ResultType}
* @param {Boolean} negative - Whether we are currently in a negative prompt field
* @returns {Promise<Number>} The use count of the tag
*/
@@ -330,7 +330,7 @@ class TacUtils {
* Retrieves the use counts of multiple tags at once from the database for improved performance
* during typing.
* @param {String[]} tagNames - An array of tag names
* @param {ResultType[]} types - An array of tag types as mapped in {@link ResultType}
* @param {TAC.ResultType[]} types - An array of tag types as mapped in {@link TAC.ResultType}
* @param {Boolean} negative - Whether we are currently in a negative prompt field
* @returns {Promise<Array>} The use count array mapped to named fields by {@link mapUseCountArray}
*/
@@ -357,7 +357,7 @@ class TacUtils {
/**
* Resets the use count of the given tag back to zero.
* @param {String} tagName - The name of the tag
* @param {ResultType} type - The type of the tag as mapped in {@link ResultType}
* @param {TAC.ResultType} type - The type of the tag as mapped in {@link TAC.ResultType}
* @param {Boolean} resetPosCount - Whether to reset the positive count
* @param {Boolean} resetNegCount - Whether to reset the negative count
*/
@@ -497,12 +497,12 @@ class TacUtils {
const textSort = (a, b, reverse = false) => {
// Assign keys so next sort is faster
if (!a.sortKey) {
a.sortKey = a.type === ResultType.chant
a.sortKey = a.type === TAC.ResultType.chant
? a.aliases
: a.text;
}
if (!b.sortKey) {
b.sortKey = b.type === ResultType.chant
b.sortKey = b.type === TAC.ResultType.chant
? b.aliases
: b.text;
}

View File

@@ -19,7 +19,7 @@ class ChantParser extends BaseTagParser {
// Add final results
let finalResults = [];
tempResults.forEach(t => {
let result = new AutocompleteResult(t.content.trim(), ResultType.chant)
let result = new TAC.TAC.AutocompleteResult(t.content.trim(), TAC.ResultType.chant)
result.meta = "Chant";
result.aliases = t.name;
result.category = t.color;
@@ -43,7 +43,7 @@ async function load() {
}
function sanitize(tagType, text) {
if (tagType === ResultType.chant) {
if (tagType === TAC.ResultType.chant) {
return text;
}
return null;

View File

@@ -36,7 +36,7 @@ class EmbeddingParser extends BaseTagParser {
let lastSlash = t[0].lastIndexOf("/") > -1 ? t[0].lastIndexOf("/") : -1;
let name = t[0].trim().substring(lastSlash + 1, lastDot);
let result = new AutocompleteResult(name, ResultType.embedding)
let result = new TAC.AutocompleteResult(name, TAC.ResultType.embedding)
result.sortKey = t[1];
result.meta = t[2] + " Embedding";
finalResults.push(result);
@@ -59,7 +59,7 @@ async function load() {
}
function sanitize(tagType, text) {
if (tagType === ResultType.embedding) {
if (tagType === TAC.ResultType.embedding) {
return text;
}
return null;

View File

@@ -19,7 +19,7 @@ class HypernetParser extends BaseTagParser {
// Add final results
let finalResults = [];
tempResults.forEach(t => {
let result = new AutocompleteResult(t[0].trim(), ResultType.hypernetwork)
let result = new TAC.AutocompleteResult(t[0].trim(), TAC.ResultType.hypernetwork)
result.meta = "Hypernetwork";
result.sortKey = t[1];
finalResults.push(result);
@@ -42,7 +42,7 @@ async function load() {
}
function sanitize(tagType, text) {
if (tagType === ResultType.hypernetwork) {
if (tagType === TAC.ResultType.hypernetwork) {
return `<hypernet:${text}:${TAC.CFG.extraNetworksDefaultMultiplier}>`;
}
return null;

View File

@@ -24,7 +24,7 @@ class LoraParser extends BaseTagParser {
let lastSlash = text.lastIndexOf("/") > -1 ? text.lastIndexOf("/") : -1;
let name = text.substring(lastSlash + 1, lastDot);
let result = new AutocompleteResult(name, ResultType.lora)
let result = new TAC.AutocompleteResult(name, TAC.ResultType.lora)
result.meta = "Lora";
result.sortKey = t[1];
result.hash = t[2];
@@ -48,7 +48,7 @@ async function load() {
}
async function sanitize(tagType, text) {
if (tagType === ResultType.lora) {
if (tagType === TAC.ResultType.lora) {
let multiplier = TAC.CFG.extraNetworksDefaultMultiplier;
let info = await TacUtils.fetchAPI(`tacapi/v1/lora-info/${text}`)
if (info && info["preferred weight"]) {

View File

@@ -24,7 +24,7 @@ class LycoParser extends BaseTagParser {
let lastSlash = text.lastIndexOf("/") > -1 ? text.lastIndexOf("/") : -1;
let name = text.substring(lastSlash + 1, lastDot);
let result = new AutocompleteResult(name, ResultType.lyco)
let result = new TAC.AutocompleteResult(name, TAC.ResultType.lyco)
result.meta = "Lyco";
result.sortKey = t[1];
result.hash = t[2];
@@ -48,7 +48,7 @@ async function load() {
}
async function sanitize(tagType, text) {
if (tagType === ResultType.lyco) {
if (tagType === TAC.ResultType.lyco) {
let multiplier = TAC.CFG.extraNetworksDefaultMultiplier;
let info = await TacUtils.fetchAPI(`tacapi/v1/lyco-info/${text}`)
if (info && info["preferred weight"]) {

View File

@@ -30,7 +30,7 @@ class StyleParser extends BaseTagParser {
// Add final results
let finalResults = [];
tempResults.forEach(t => {
let result = new AutocompleteResult(t[0].trim(), ResultType.styleName)
let result = new TAC.AutocompleteResult(t[0].trim(), TAC.ResultType.styleName)
result.meta = "Style";
finalResults.push(result);
});
@@ -53,7 +53,7 @@ async function load(force = false) {
}
function sanitize(tagType, text) {
if (tagType === ResultType.styleName) {
if (tagType === TAC.ResultType.styleName) {
if (text.includes(" ")) {
return `$${lastStyleVarIndex}(${text})`;
} else {

View File

@@ -144,7 +144,7 @@ class UmiParser extends BaseTagParser {
// Add final results
let finalResults = [];
tempResults.forEach(t => {
let result = new AutocompleteResult(t[0].trim(), ResultType.umiWildcard)
let result = new TAC.AutocompleteResult(t[0].trim(), TAC.ResultType.umiWildcard)
result.count = t[1];
finalResults.push(result);
});
@@ -157,7 +157,7 @@ class UmiParser extends BaseTagParser {
// Add final results
let finalResults = [];
filteredWildcardsSorted.forEach(t => {
let result = new AutocompleteResult(t[0].trim(), ResultType.umiWildcard)
let result = new TAC.AutocompleteResult(t[0].trim(), TAC.ResultType.umiWildcard)
result.count = t[1];
finalResults.push(result);
});
@@ -174,7 +174,7 @@ class UmiParser extends BaseTagParser {
// Add final results
let finalResults = [];
filteredWildcardsSorted.forEach(t => {
let result = new AutocompleteResult(t[0].trim(), ResultType.umiWildcard)
let result = new TAC.AutocompleteResult(t[0].trim(), TAC.ResultType.umiWildcard)
result.count = t[1];
finalResults.push(result);
});
@@ -190,7 +190,7 @@ class UmiParser extends BaseTagParser {
function updateUmiTags(tagType, sanitizedText, newPrompt, textArea) {
// If it was a umi wildcard, also update the TAC.Globals.umiPreviousTags
if (tagType === ResultType.umiWildcard && TAC.Globals.originalTagword.length > 0) {
if (tagType === TAC.ResultType.umiWildcard && TAC.Globals.originalTagword.length > 0) {
let umiSubPrompts = [...newPrompt.matchAll(UMI_PROMPT_REGEX)];
let umiTags = [];
@@ -230,7 +230,7 @@ async function load() {
function sanitize(tagType, text) {
// Replace underscores only if the umi tag is not using them
if (tagType === ResultType.umiWildcard && !TAC.Globals.umiWildcards.includes(text)) {
if (tagType === TAC.ResultType.umiWildcard && !TAC.Globals.umiWildcards.includes(text)) {
return text.replaceAll("_", " ");
}
return null;

View File

@@ -51,7 +51,7 @@ class WildcardParser extends BaseTagParser {
let finalResults = [];
let tempResults = wildcards.filter(x => (wcWord !== null && wcWord.length > 0) ? x.toLowerCase().includes(wcWord) : x) // Filter by tagword
tempResults.forEach(t => {
let result = new AutocompleteResult(t.trim(), ResultType.wildcardTag);
let result = new TAC.AutocompleteResult(t.trim(), TAC.ResultType.wildcardTag);
result.meta = wcFile;
finalResults.push(result);
});
@@ -80,10 +80,10 @@ class WildcardFileParser extends BaseTagParser {
let result = null;
if (wcFile[0].endsWith(".yaml")) {
result = new AutocompleteResult(wcFile[1].trim(), ResultType.yamlWildcard);
result = new TAC.AutocompleteResult(wcFile[1].trim(), TAC.ResultType.yamlWildcard);
result.meta = "YAML wildcard collection";
} else {
result = new AutocompleteResult(wcFile[1].trim(), ResultType.wildcardFile);
result = new TAC.AutocompleteResult(wcFile[1].trim(), TAC.ResultType.wildcardFile);
result.meta = "Wildcard file";
result.sortKey = wcFile[2].trim();
}
@@ -150,9 +150,9 @@ async function load() {
}
function sanitize(tagType, text) {
if (tagType === ResultType.wildcardFile || tagType === ResultType.yamlWildcard) {
if (tagType === TAC.ResultType.wildcardFile || tagType === TAC.ResultType.yamlWildcard) {
return `${TAC.CFG.wcWrap}${text}${TAC.CFG.wcWrap}`;
} else if (tagType === ResultType.wildcardTag) {
} else if (tagType === TAC.ResultType.wildcardTag) {
return text;
}
return null;
@@ -160,7 +160,7 @@ function sanitize(tagType, text) {
function keepOpenIfWildcard(tagType, sanitizedText, newPrompt, textArea) {
// If it's a wildcard, we want to keep the results open so the user can select another wildcard
if (tagType === ResultType.wildcardFile || tagType === ResultType.yamlWildcard) {
if (tagType === TAC.ResultType.wildcardFile || tagType === TAC.ResultType.yamlWildcard) {
TAC.Globals.hideBlocked = true;
setTimeout(() => { TAC.Globals.hideBlocked = false; }, 450);
return true;

View File

@@ -446,7 +446,7 @@ async function insertTextAtCursor(textArea, result, tagword, tabCompletedWithout
} else {
sanitizedText = text;
}
if (TAC.CFG.escapeParentheses && tagType === ResultType.tag) {
if (TAC.CFG.escapeParentheses && tagType === TAC.ResultType.tag) {
sanitizedText = sanitizedText
.replaceAll("(", "\\(")
.replaceAll(")", "\\)")
@@ -455,7 +455,7 @@ async function insertTextAtCursor(textArea, result, tagword, tabCompletedWithout
}
}
if ((tagType === ResultType.wildcardFile || tagType === ResultType.yamlWildcard)
if ((tagType === TAC.ResultType.wildcardFile || tagType === TAC.ResultType.yamlWildcard)
&& tabCompletedWithoutChoice
&& TAC.CFG.wildcardCompletionMode !== "Always fully"
&& sanitizedText.includes("/")) {
@@ -496,13 +496,13 @@ async function insertTextAtCursor(textArea, result, tagword, tabCompletedWithout
let name = null;
switch (tagType) {
case ResultType.wildcardFile:
case ResultType.yamlWildcard:
case TAC.ResultType.wildcardFile:
case TAC.ResultType.yamlWildcard:
// We only want to update the frequency for a full wildcard, not partial paths
if (sanitizedText.endsWith(TAC.CFG.wcWrap))
name = text
break;
case ResultType.chant:
case TAC.ResultType.chant:
// Chants use a slightly different format
name = result.aliases;
break;
@@ -532,8 +532,8 @@ async function insertTextAtCursor(textArea, result, tagword, tabCompletedWithout
let afterInsertCursorPos = editStart + match.index + sanitizedText.length;
var optionalSeparator = "";
let extraNetworkTypes = [ResultType.hypernetwork, ResultType.lora];
let noCommaTypes = [ResultType.wildcardFile, ResultType.yamlWildcard, ResultType.umiWildcard].concat(extraNetworkTypes);
let extraNetworkTypes = [TAC.ResultType.hypernetwork, TAC.ResultType.lora];
let noCommaTypes = [TAC.ResultType.wildcardFile, TAC.ResultType.yamlWildcard, TAC.ResultType.umiWildcard].concat(extraNetworkTypes);
if (!noCommaTypes.includes(tagType)) {
// Append comma if enabled and not already present
let beforeComma = surrounding.match(new RegExp(`${TacUtils.escapeRegExp(tagword)}[,:]`, "i")) !== null;
@@ -563,10 +563,10 @@ async function insertTextAtCursor(textArea, result, tagword, tabCompletedWithout
// Add lora/lyco keywords if enabled and found
let keywordsLength = 0;
if (TAC.CFG.modelKeywordCompletion !== "Never" && (tagType === ResultType.lora || tagType === ResultType.lyco)) {
if (TAC.CFG.modelKeywordCompletion !== "Never" && (tagType === TAC.ResultType.lora || tagType === TAC.ResultType.lyco)) {
let keywords = null;
// Check built-in activation words first
if (tagType === ResultType.lora || tagType === ResultType.lyco) {
if (tagType === TAC.ResultType.lora || tagType === TAC.ResultType.lyco) {
let info = await TacUtils.fetchAPI(`tacapi/v1/lora-info/${result.text}`)
if (info && info["activation text"]) {
keywords = info["activation text"];
@@ -626,11 +626,11 @@ async function insertTextAtCursor(textArea, result, tagword, tabCompletedWithout
textArea.selectionEnd = textArea.selectionStart
// Set self trigger flag to show wildcard contents after the filename was inserted
if ([ResultType.wildcardFile, ResultType.yamlWildcard, ResultType.umiWildcard].includes(result.type))
if ([TAC.ResultType.wildcardFile, TAC.ResultType.yamlWildcard, TAC.ResultType.umiWildcard].includes(result.type))
TAC.Globals.selfTrigger = true;
// Since we've modified a Gradio Textbox component manually, we need to simulate an `input` DOM event to ensure it's propagated back to python.
// Uses a built-in method from the webui's ui.js which also already accounts for event target
if (tagType === ResultType.wildcardTag || tagType === ResultType.wildcardFile || tagType === ResultType.yamlWildcard)
if (tagType === TAC.ResultType.wildcardTag || tagType === TAC.ResultType.wildcardFile || tagType === TAC.ResultType.yamlWildcard)
TAC.Globals.selfTrigger = true;
updateInput(textArea);
@@ -736,7 +736,7 @@ function addResultsToList(textArea, results, tagword, resetList) {
let displayText = "";
// If the tag matches the tagword, we don't need to display the alias
if(result.type === ResultType.chant) {
if(result.type === TAC.ResultType.chant) {
displayText = TacUtils.escapeHTML(result.aliases);
} else if (result.aliases && !result.text.includes(tagword)) { // Alias
let splitAliases = result.aliases.split(",");
@@ -772,7 +772,7 @@ function addResultsToList(textArea, results, tagword, resetList) {
// Print search term bolded in result
itemText.innerHTML = displayText.replace(tagword, `<b>${tagword}</b>`);
const splitTypes = [ResultType.wildcardFile, ResultType.yamlWildcard]
const splitTypes = [TAC.ResultType.wildcardFile, TAC.ResultType.yamlWildcard]
if (splitTypes.includes(result.type) && itemText.innerHTML.includes("/")) {
let parts = itemText.innerHTML.split("/");
let lastPart = parts[parts.length - 1];
@@ -784,7 +784,7 @@ function addResultsToList(textArea, results, tagword, resetList) {
// Add wiki link if the setting is enabled and a supported tag set loaded
if (
TAC.CFG.showWikiLinks &&
result.type === ResultType.tag &&
result.type === TAC.ResultType.tag &&
IS_DAN_OR_E621_TAG_FILE
) {
let wikiLink = document.createElement("a");
@@ -865,7 +865,7 @@ function addResultsToList(textArea, results, tagword, resetList) {
metaDiv.classList.add("acMetaText");
// Add version info classes if it is an embedding
if (result.type === ResultType.embedding) {
if (result.type === TAC.ResultType.embedding) {
if (result.meta.startsWith("v1"))
itemText.classList.add("acEmbeddingV1");
else if (result.meta.startsWith("v2"))
@@ -909,10 +909,10 @@ function addResultsToList(textArea, results, tagword, resetList) {
if (
TAC.CFG.showExtraNetworkPreviews &&
[
ResultType.embedding,
ResultType.hypernetwork,
ResultType.lora,
ResultType.lyco,
TAC.ResultType.embedding,
TAC.ResultType.hypernetwork,
TAC.ResultType.lora,
TAC.ResultType.lyco,
].includes(result.type)
) {
li.addEventListener("mouseover", async () => {
@@ -973,14 +973,14 @@ async function updateSelectionStyle(textArea, newIndex, oldIndex, scroll = true)
let selectedResult = TAC.Globals.results[newIndex];
let selectedType = selectedResult.type;
// These types support previews (others could technically too, but are not native to the webui gallery)
let previewTypes = [ResultType.embedding, ResultType.hypernetwork, ResultType.lora, ResultType.lyco];
let previewTypes = [TAC.ResultType.embedding, TAC.ResultType.hypernetwork, TAC.ResultType.lora, TAC.ResultType.lyco];
let previewDiv = gradioApp().querySelector(`.autocompleteParent${textAreaId} .sideInfo`);
if (TAC.CFG.showExtraNetworkPreviews && previewTypes.includes(selectedType)) {
let img = previewDiv.querySelector("img");
// String representation of our type enum
const typeString = Object.keys(ResultType)[selectedType - 1].toLowerCase();
const typeString = Object.keys(TAC.ResultType)[selectedType - 1].toLowerCase();
// Get image from API
let url = await TacUtils.getExtraNetworkPreviewURL(selectedResult.text, typeString);
if (url) {
@@ -1217,7 +1217,7 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
// Flatten our candidate(s)
TAC.Globals.results = resultCandidates.flat();
// Sort results, but not if it's umi tags since they are sorted by count
if (!(resultCandidates.length === 1 && TAC.Globals.results[0].type === ResultType.umiWildcard))
if (!(resultCandidates.length === 1 && TAC.Globals.results[0].type === TAC.ResultType.umiWildcard))
TAC.Globals.results = TAC.Globals.results.sort(TacUtils.getSortFunction());
}
// Else search the normal tag list
@@ -1254,7 +1254,7 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
// Add final results
TAC.Globals.allTags.filter(fil).forEach(t => {
let result = new AutocompleteResult(t[0].trim(), ResultType.tag)
let result = new TAC.AutocompleteResult(t[0].trim(), TAC.ResultType.tag)
result.category = t[1];
result.count = t[2];
result.aliases = t[3];
@@ -1266,7 +1266,7 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
let extraResults = [];
TAC.Globals.extras.filter(fil).forEach(e => {
let result = new AutocompleteResult(e[0].trim(), ResultType.extra)
let result = new TAC.AutocompleteResult(e[0].trim(), TAC.ResultType.extra)
result.category = e[1] || 0; // If no category is given, use 0 as the default
result.meta = e[2] || "Custom tag";
result.aliases = e[3] || "";
@@ -1295,9 +1295,9 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
let aliasNames = [];
let types = [];
// Limit to 2k for performance reasons
const aliasTypes = [ResultType.tag, ResultType.extra];
const aliasTypes = [TAC.ResultType.tag, TAC.ResultType.extra];
TAC.Globals.results.slice(0,2000).forEach(r => {
const name = r.type === ResultType.chant ? r.aliases : r.text;
const name = r.type === TAC.ResultType.chant ? r.aliases : r.text;
// Add to alias list or tag list depending on if the name includes the tagword
// (the same criteria is used in the filter in calculateUsageBias)
if (aliasTypes.includes(r.type) && !name.includes(TAC.Globals.tagword)) {
@@ -1319,7 +1319,7 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
// Pre-calculate weights to prevent duplicate work
const resultBiasMap = new Map();
TAC.Globals.results.forEach(result => {
const name = result.type === ResultType.chant ? result.aliases : result.text;
const name = result.type === TAC.ResultType.chant ? result.aliases : result.text;
const type = result.type;
// Find matching pair from DB results
const useStats = counts.find(c => c.name === name && c.type === type);