fix(autocomplete): remove short prompt command aliases (#895)

This commit is contained in:
Will Miao
2026-04-15 20:43:03 +08:00
parent 083de395b1
commit b910388d54
7 changed files with 19 additions and 23 deletions

View File

@@ -101,7 +101,7 @@ Insomnia Art Designs, megakirbs, Brennok, 2018cfh, W+K+White, wackop, Takkan, Ca
### v0.9.14 ### v0.9.14
* **LoRA Cycler Node** - Introduced a new LoRA Cycler node that enables iteration through specified LoRAs with support for repeat count and pause iteration functionality. Refer to the new "Lora Cycler" template workflow for concrete example. * **LoRA Cycler Node** - Introduced a new LoRA Cycler node that enables iteration through specified LoRAs with support for repeat count and pause iteration functionality. Refer to the new "Lora Cycler" template workflow for concrete example.
* **Enhanced Prompt Node with Tag Autocomplete** - Enhanced the Prompt node with comprehensive tag autocomplete based on merged Danbooru + e621 tags. Supports tag search and autocomplete functionality. Implemented a command system with shortcuts like `/char` or `/artist` for category-specific tag searching. Added `/ac` or `/noac` commands to quickly enable or disable autocomplete. Refer to the "Lora Manager Basic" template workflow in ComfyUI -> Templates -> ComfyUI-Lora-Manager for detailed tips. * **Enhanced Prompt Node with Tag Autocomplete** - Enhanced the Prompt node with comprehensive tag autocomplete based on merged Danbooru + e621 tags. Supports tag search and autocomplete functionality. Implemented a command system with shortcuts like `/character` or `/artist` for category-specific tag searching. Added `/ac` or `/noac` commands to quickly enable or disable autocomplete. Refer to the "Lora Manager Basic" template workflow in ComfyUI -> Templates -> ComfyUI-Lora-Manager for detailed tips.
* **Bug Fixes & Stability** - Addressed multiple bugs and improved overall stability. * **Bug Fixes & Stability** - Addressed multiple bugs and improved overall stability.
### v0.9.12 ### v0.9.12

File diff suppressed because one or more lines are too long

View File

@@ -71,8 +71,8 @@ class PromptLM:
"AUTOCOMPLETE_TEXT_PROMPT,STRING", "AUTOCOMPLETE_TEXT_PROMPT,STRING",
{ {
"widgetType": "AUTOCOMPLETE_TEXT_PROMPT", "widgetType": "AUTOCOMPLETE_TEXT_PROMPT",
"placeholder": "Enter prompt... /char, /artist, /wild for quick search", "placeholder": "Enter prompt... /character, /artist, /wildcard for quick search",
"tooltip": "The text to be encoded. Wildcard references inserted with /wild are expanded at runtime.", "tooltip": "The text to be encoded. Wildcard references inserted with /wildcard are expanded at runtime.",
}, },
), ),
"clip": ( "clip": (

View File

@@ -20,8 +20,8 @@ class TextLM:
"AUTOCOMPLETE_TEXT_PROMPT,STRING", "AUTOCOMPLETE_TEXT_PROMPT,STRING",
{ {
"widgetType": "AUTOCOMPLETE_TEXT_PROMPT", "widgetType": "AUTOCOMPLETE_TEXT_PROMPT",
"placeholder": "Enter text... /char, /artist, /wild for quick search", "placeholder": "Enter text... /character, /artist, /wildcard for quick search",
"tooltip": "The text output. Wildcard references inserted with /wild are expanded at runtime.", "tooltip": "The text output. Wildcard references inserted with /wildcard are expanded at runtime.",
}, },
), ),
}, },

View File

@@ -286,7 +286,6 @@ describe('AutoComplete widget interactions', () => {
const commandNames = autoComplete.items.map((item) => item.command); const commandNames = autoComplete.items.map((item) => item.command);
expect(commandNames).toContain('/character'); expect(commandNames).toContain('/character');
expect(commandNames).toContain('/char');
expect(commandNames).toContain('/artist'); expect(commandNames).toContain('/artist');
expect(commandNames).toContain('/general'); expect(commandNames).toContain('/general');
expect(commandNames).toContain('/copyright'); expect(commandNames).toContain('/copyright');
@@ -295,7 +294,6 @@ describe('AutoComplete widget interactions', () => {
expect(commandNames).toContain('/lore'); expect(commandNames).toContain('/lore');
expect(commandNames).toContain('/emb'); expect(commandNames).toContain('/emb');
expect(commandNames).toContain('/embedding'); expect(commandNames).toContain('/embedding');
expect(commandNames).toContain('/wild');
expect(commandNames).toContain('/wildcard'); expect(commandNames).toContain('/wildcard');
}); });
@@ -817,12 +815,12 @@ describe('AutoComplete widget interactions', () => {
json: () => Promise.resolve({ success: true, words: mockTags }), json: () => Promise.resolve({ success: true, words: mockTags }),
}); });
// Simulate "/char looking to the side" input // Simulate "/character looking to the side" input
caretHelperInstance.getBeforeCursor.mockReturnValue('/char looking to the side'); caretHelperInstance.getBeforeCursor.mockReturnValue('/character looking to the side');
caretHelperInstance.getCursorOffset.mockReturnValue({ left: 15, top: 25 }); caretHelperInstance.getCursorOffset.mockReturnValue({ left: 15, top: 25 });
const input = document.createElement('textarea'); const input = document.createElement('textarea');
input.value = '/char looking to the side'; input.value = '/character looking to the side';
input.selectionStart = input.value.length; input.selectionStart = input.value.length;
input.focus = vi.fn(); input.focus = vi.fn();
input.setSelectionRange = vi.fn(); input.setSelectionRange = vi.fn();
@@ -840,7 +838,7 @@ describe('AutoComplete widget interactions', () => {
autoComplete.activeCommand = { categories: [4, 11], label: 'Character' }; autoComplete.activeCommand = { categories: [4, 11], label: 'Character' };
autoComplete.items = mockTags; autoComplete.items = mockTags;
autoComplete.selectedIndex = 0; autoComplete.selectedIndex = 0;
autoComplete.currentSearchTerm = '/char looking to the side'; autoComplete.currentSearchTerm = '/character looking to the side';
await autoComplete.insertSelection('looking_to_the_side'); await autoComplete.insertSelection('looking_to_the_side');
@@ -1147,18 +1145,18 @@ describe('AutoComplete widget interactions', () => {
expect(fetchApiMock).toHaveBeenCalledWith('/lm/custom-words/search?enriched=true&search=cat&limit=100'); expect(fetchApiMock).toHaveBeenCalledWith('/lm/custom-words/search?enriched=true&search=cat&limit=100');
}); });
it('searches wildcard keys when using the /wild command', async () => { it('searches wildcard keys when using the /wildcard command', async () => {
vi.useFakeTimers(); vi.useFakeTimers();
fetchApiMock.mockResolvedValue({ fetchApiMock.mockResolvedValue({
json: () => Promise.resolve({ success: true, words: ['animals/cat'] }), json: () => Promise.resolve({ success: true, words: ['animals/cat'] }),
}); });
caretHelperInstance.getBeforeCursor.mockReturnValue('/wild cat'); caretHelperInstance.getBeforeCursor.mockReturnValue('/wildcard cat');
caretHelperInstance.getCursorOffset.mockReturnValue({ left: 15, top: 25 }); caretHelperInstance.getCursorOffset.mockReturnValue({ left: 15, top: 25 });
const input = document.createElement('textarea'); const input = document.createElement('textarea');
input.value = '/wild cat'; input.value = '/wildcard cat';
input.selectionStart = input.value.length; input.selectionStart = input.value.length;
document.body.append(input); document.body.append(input);
@@ -1179,11 +1177,11 @@ describe('AutoComplete widget interactions', () => {
expect(autoComplete.items).toEqual(['animals/cat']); expect(autoComplete.items).toEqual(['animals/cat']);
}); });
it('inserts wildcard references when accepting a /wild result', async () => { it('inserts wildcard references when accepting a /wildcard result', async () => {
caretHelperInstance.getBeforeCursor.mockReturnValue('/wild animals/cat'); caretHelperInstance.getBeforeCursor.mockReturnValue('/wildcard animals/cat');
const input = document.createElement('textarea'); const input = document.createElement('textarea');
input.value = '/wild animals/cat'; input.value = '/wildcard animals/cat';
input.selectionStart = input.value.length; input.selectionStart = input.value.length;
input.focus = vi.fn(); input.focus = vi.fn();
input.setSelectionRange = vi.fn(); input.setSelectionRange = vi.fn();

View File

@@ -19,7 +19,6 @@ import { showToast } from "./utils.js";
// Command definitions for category filtering // Command definitions for category filtering
const TAG_COMMANDS = { const TAG_COMMANDS = {
'/character': { categories: [4, 11], label: 'Character' }, '/character': { categories: [4, 11], label: 'Character' },
'/char': { categories: [4, 11], label: 'Character' },
'/artist': { categories: [1, 8], label: 'Artist' }, '/artist': { categories: [1, 8], label: 'Artist' },
'/general': { categories: [0, 7], label: 'General' }, '/general': { categories: [0, 7], label: 'General' },
'/copyright': { categories: [3, 10], label: 'Copyright' }, '/copyright': { categories: [3, 10], label: 'Copyright' },
@@ -1270,7 +1269,7 @@ class AutoComplete {
}; };
} }
// Command with search term (e.g., "/char miku") // Command with search term (e.g., "/character miku")
const commandPart = trimmed.slice(0, spaceIndex).toLowerCase(); const commandPart = trimmed.slice(0, spaceIndex).toLowerCase();
const searchPart = trimmed.slice(spaceIndex + 1).trim(); const searchPart = trimmed.slice(spaceIndex + 1).trim();
@@ -1417,7 +1416,7 @@ class AutoComplete {
/** /**
* Insert a command into the input * Insert a command into the input
* @param {string} command - The command to insert (e.g., "/char") * @param {string} command - The command to insert (e.g., "/character")
*/ */
_insertCommand(command) { _insertCommand(command) {
const currentValue = this.inputElement.value; const currentValue = this.inputElement.value;
@@ -2310,7 +2309,7 @@ class AutoComplete {
// This allows "hello 1gi" + selecting "1girl" to become "hello 1girl, " // This allows "hello 1gi" + selecting "1girl" to become "hello 1girl, "
// However, if the user typed a multi-word phrase that matches a tag (e.g., "looking to the side" // However, if the user typed a multi-word phrase that matches a tag (e.g., "looking to the side"
// matching "looking_to_the_side"), replace the entire phrase instead of just the last word. // matching "looking_to_the_side"), replace the entire phrase instead of just the last word.
// Command mode (e.g., "/char miku") should replace the entire command+search // Command mode (e.g., "/character miku") should replace the entire command+search
let searchTerm = fullSearchTerm; let searchTerm = fullSearchTerm;
if (this.modelType === 'prompt' && this.searchType === 'custom_words' && !this.activeCommand) { if (this.modelType === 'prompt' && this.searchType === 'custom_words' && !this.activeCommand) {
// Check if the selectedItem exists and its tag_name matches the full search term // Check if the selectedItem exists and its tag_name matches the full search term

View File

@@ -1,5 +1,4 @@
export const WILDCARD_COMMANDS = { export const WILDCARD_COMMANDS = {
'/wild': { type: 'wildcard', label: 'Wildcards' },
'/wildcard': { type: 'wildcard', label: 'Wildcards' }, '/wildcard': { type: 'wildcard', label: 'Wildcards' },
}; };