| 103 | this.apiId = apiId; | 104 | this.apiId = apiId; |
| 104 | } | 105 | } |
| 105 | | 106 | |
| | 107 | static masterSections = { |
| | 108 | 'instruct': { |
| | 109 | name: 'Instruct Template', |
| | 110 | getData: () => { |
| | 111 | const manager = getPresetManager('instruct'); |
| | 112 | const name = manager.getSelectedPresetName(); |
| | 113 | return manager.getPresetSettings(name); |
| | 114 | }, |
| | 115 | setData: (data) => { |
| | 116 | const manager = getPresetManager('instruct'); |
| | 117 | const name = data.name; |
| | 118 | return manager.savePreset(name, data); |
| | 119 | }, |
| | 120 | isValid: (data) => PresetManager.isPossiblyInstructData(data), |
| | 121 | }, |
| | 122 | 'context': { |
| | 123 | name: 'Context Template', |
| | 124 | getData: () => { |
| | 125 | const manager = getPresetManager('context'); |
| | 126 | const name = manager.getSelectedPresetName(); |
| | 127 | return manager.getPresetSettings(name); |
| | 128 | }, |
| | 129 | setData: (data) => { |
| | 130 | const manager = getPresetManager('context'); |
| | 131 | const name = data.name; |
| | 132 | return manager.savePreset(name, data); |
| | 133 | }, |
| | 134 | isValid: (data) => PresetManager.isPossiblyContextData(data), |
| | 135 | }, |
| | 136 | 'sysprompt': { |
| | 137 | name: 'System Prompt', |
| | 138 | getData: () => { |
| | 139 | const manager = getPresetManager('sysprompt'); |
| | 140 | const name = manager.getSelectedPresetName(); |
| | 141 | return manager.getPresetSettings(name); |
| | 142 | }, |
| | 143 | setData: (data) => { |
| | 144 | const manager = getPresetManager('sysprompt'); |
| | 145 | const name = data.name; |
| | 146 | return manager.savePreset(name, data); |
| | 147 | }, |
| | 148 | isValid: (data) => PresetManager.isPossiblySystemPromptData(data), |
| | 149 | }, |
| | 150 | 'preset': { |
| | 151 | name: 'Text Completion Settings', |
| | 152 | getData: () => { |
| | 153 | const manager = getPresetManager('textgenerationwebui'); |
| | 154 | const name = manager.getSelectedPresetName(); |
| | 155 | const data = manager.getPresetSettings(name); |
| | 156 | data['name'] = name; |
| | 157 | return data; |
| | 158 | }, |
| | 159 | setData: (data) => { |
| | 160 | const manager = getPresetManager('textgenerationwebui'); |
| | 161 | const name = data.name; |
| | 162 | return manager.savePreset(name, data); |
| | 163 | }, |
| | 164 | isValid: (data) => PresetManager.isPossiblyTextCompletionData(data), |
| | 165 | }, |
| | 166 | }; |
| | 167 | |
| | 168 | static isPossiblyInstructData(data) { |
| | 169 | const instructProps = ['name', 'input_sequence', 'output_sequence']; |
| | 170 | return data && instructProps.every(prop => Object.keys(data).includes(prop)); |
| | 171 | } |
| | 172 | |
| | 173 | static isPossiblyContextData(data) { |
| | 174 | const contextProps = ['name', 'story_string']; |
| | 175 | return data && contextProps.every(prop => Object.keys(data).includes(prop)); |
| | 176 | } |
| | 177 | |
| | 178 | static isPossiblySystemPromptData(data) { |
| | 179 | const sysPromptProps = ['name', 'content']; |
| | 180 | return data && sysPromptProps.every(prop => Object.keys(data).includes(prop)); |
| | 181 | } |
| | 182 | |
| | 183 | static isPossiblyTextCompletionData(data) { |
| | 184 | const textCompletionProps = ['temp', 'top_k', 'top_p', 'rep_pen']; |
| | 185 | return data && textCompletionProps.every(prop => Object.keys(data).includes(prop)); |
| | 186 | } |
| | 187 | |
| | 188 | static async performMasterImport(data) { |
| | 189 | if (!data || typeof data !== 'object') { |
| | 190 | toastr.error('Invalid data provided for master import'); |
| | 191 | return; |
| | 192 | } |
| | 193 | |
| | 194 | // Check for legacy file imports |
| | 195 | // 1. Instruct Template |
| | 196 | if (this.isPossiblyInstructData(data)) { |
| | 197 | toastr.info('Importing instruct template...', 'Instruct template detected'); |
| | 198 | return await getPresetManager('instruct').savePreset(data.name, data); |
| | 199 | } |
| | 200 | |
| | 201 | // 2. Context Template |
| | 202 | if (this.isPossiblyContextData(data)) { |
| | 203 | toastr.info('Importing as context template...', 'Context template detected'); |
| | 204 | return await getPresetManager('context').savePreset(data.name, data); |
| | 205 | } |
| | 206 | |
| | 207 | // 3. System Prompt |
| | 208 | if (this.isPossiblySystemPromptData(data)) { |
| | 209 | toastr.info('Importing as system prompt...', 'System prompt detected'); |
| | 210 | return await getPresetManager('sysprompt').savePreset(data.name, data); |
| | 211 | } |
| | 212 | |
| | 213 | // 4. Text Completion settings |
| | 214 | if (this.isPossiblyTextCompletionData(data)) { |
| | 215 | toastr.info('Importing as settings preset...', 'Text Completion settings detected'); |
| | 216 | return await getPresetManager('textgenerationwebui').savePreset(data.name, data); |
| | 217 | } |
| | 218 | |
| | 219 | const validSections = []; |
| | 220 | for (const [key, section] of Object.entries(this.masterSections)) { |
| | 221 | if (key in data && section.isValid(data[key])) { |
| | 222 | validSections.push(key); |
| | 223 | } |
| | 224 | } |
| | 225 | |
| | 226 | if (validSections.length === 0) { |
| | 227 | toastr.error('No valid sections found in imported data'); |
| | 228 | return; |
| | 229 | } |
| | 230 | |
| | 231 | const sectionNames = validSections.reduce((acc, key) => { |
| | 232 | acc[key] = this.masterSections[key].name; |
| | 233 | return acc; |
| | 234 | }, {}); |
| | 235 | |
| | 236 | const html = $(await renderTemplateAsync('masterImport', { sections: sectionNames })); |
| | 237 | const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', { |
| | 238 | okButton: 'Confirm', |
| | 239 | cancelButton: 'Cancel', |
| | 240 | }); |
| | 241 | |
| | 242 | const result = await popup.show(); |
| | 243 | |
| | 244 | // Import cancelled |
| | 245 | if (result !== POPUP_RESULT.AFFIRMATIVE) { |
| | 246 | return; |
| | 247 | } |
| | 248 | |
| | 249 | const importedSections = []; |
| | 250 | const confirmedSections = html.find('input:checked').map((_, el) => el instanceof HTMLInputElement && el.value).get(); |
| | 251 | |
| | 252 | if (confirmedSections.length === 0) { |
| | 253 | toastr.info('No sections selected for import'); |
| | 254 | return; |
| | 255 | } |
| | 256 | |
| | 257 | for (const section of confirmedSections) { |
| | 258 | const sectionData = data[section]; |
| | 259 | const masterSection = this.masterSections[section]; |
| | 260 | if (sectionData && masterSection) { |
| | 261 | await masterSection.setData(sectionData); |
| | 262 | importedSections.push(masterSection.name); |
| | 263 | } |
| | 264 | } |
| | 265 | |
| | 266 | toastr.success(`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`); |
| | 267 | } |
| | 268 | |
| | 269 | static async performMasterExport() { |
| | 270 | const sectionNames = Object.entries(this.masterSections).reduce((acc, [key, section]) => { |
| | 271 | acc[key] = section.name; |
| | 272 | return acc; |
| | 273 | }, {}); |
| | 274 | const html = $(await renderTemplateAsync('masterExport', { sections: sectionNames })); |
| | 275 | |
| | 276 | const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', { |
| | 277 | okButton: 'Export', |
| | 278 | cancelButton: 'Cancel', |
| | 279 | }); |
| | 280 | |
| | 281 | const result = await popup.show(); |
| | 282 | |
| | 283 | // Export cancelled |
| | 284 | if (result !== POPUP_RESULT.AFFIRMATIVE) { |
| | 285 | return; |
| | 286 | } |
| | 287 | |
| | 288 | const confirmedSections = html.find('input:checked').map((_, el) => el instanceof HTMLInputElement && el.value).get(); |
| | 289 | const data = {}; |
| | 290 | |
| | 291 | if (confirmedSections.length === 0) { |
| | 292 | toastr.info('No sections selected for export'); |
| | 293 | return; |
| | 294 | } |
| | 295 | |
| | 296 | for (const section of confirmedSections) { |
| | 297 | const masterSection = this.masterSections[section]; |
| | 298 | if (masterSection) { |
| | 299 | data[section] = masterSection.getData(); |
| | 300 | } |
| | 301 | } |
| | 302 | |
| | 303 | return JSON.stringify(data, null, 4); |
| | 304 | } |
| | 305 | |
| 106 | /** | 306 | /** |
| 107 | * Gets all preset names. | 307 | * Gets all preset names. |
| 108 | * @returns {string[]} List of preset names | 308 | * @returns {string[]} List of preset names |