Migrate substituteParams calls to new engine (#4901)
Signed| @@ -3159,10 +3159,19 @@ export async function getExtensionPrompt(position = extension_prompt_types.IN_PR | |||
| 3159 | return values; | 3159 | return values; |
| 3160 | } | 3160 | } |
| 3161 | 3161 | ||
| 3162 | export function baseChatReplace(value, name1, name2) { | 3162 | /** |
| 3163 | if (value !== undefined && value.length > 0) { | 3163 | * Base chat replacement function for character card fields. |
| 3164 | const _ = undefined; | 3164 | * 1. Substitutes macros using substituteParams. |
| 3165 | value = substituteParams(value, name1, name2, _, _, false); | 3165 | * 2. Collapses newlines if enabled in power user settings. |
| 3166 | * 3. Removes carriage return characters. | ||
| 3167 | * @param {string} value Input string | ||
| 3168 | * @param {string?} name1Override Override for name1 | ||
| 3169 | * @param {string?} name2Override Override for name2 | ||
| 3170 | * @returns {string} Processed string | ||
| 3171 | */ | ||
| 3172 | export function baseChatReplace(value, name1Override = null, name2Override = null) { | ||
| 3173 | if (typeof value === 'string' && value.length > 0) { | ||
| 3174 | value = substituteParams(value, { name1Override, name2Override, replaceCharacterCard: false }); | ||
| 3166 | 3175 | ||
| 3167 | if (power_user.collapse_newlines) { | 3176 | if (power_user.collapse_newlines) { |
| 3168 | value = collapseNewlines(value); | 3177 | value = collapseNewlines(value); |
| @@ -3229,47 +3238,47 @@ export function getCharacterCardFieldsLazy({ chid = undefined } = {}) { | |||
| 3229 | 3238 | ||
| 3230 | /** @type {Record<string, () => string>} */ | 3239 | /** @type {Record<string, () => string>} */ |
| 3231 | const resolvers = { | 3240 | const resolvers = { |
| 3232 | persona: () => baseChatReplace(power_user.persona_description?.trim(), name1, name2), | 3241 | persona: () => baseChatReplace(power_user.persona_description?.trim()), |
| 3233 | system: () => { | 3242 | system: () => { |
| 3234 | if (!character) return ''; | 3243 | if (!character) return ''; |
| 3235 | const systemPrompt = chat_metadata['system_prompt'] || character.data?.system_prompt || ''; | 3244 | const systemPrompt = chat_metadata['system_prompt'] || character.data?.system_prompt || ''; |
| 3236 | return power_user.prefer_character_prompt ? baseChatReplace(systemPrompt.trim(), name1, name2) : ''; | 3245 | return power_user.prefer_character_prompt ? baseChatReplace(systemPrompt.trim()) : ''; |
| 3237 | }, | 3246 | }, |
| 3238 | jailbreak: () => { | 3247 | jailbreak: () => { |
| 3239 | if (!character) return ''; | 3248 | if (!character) return ''; |
| 3240 | return power_user.prefer_character_jailbreak ? baseChatReplace(character.data?.post_history_instructions?.trim(), name1, name2) : ''; | 3249 | return power_user.prefer_character_jailbreak ? baseChatReplace(character.data?.post_history_instructions?.trim()) : ''; |
| 3241 | }, | 3250 | }, |
| 3242 | version: () => character?.data?.character_version ?? '', | 3251 | version: () => character?.data?.character_version ?? '', |
| 3243 | charDepthPrompt: () => { | 3252 | charDepthPrompt: () => { |
| 3244 | if (!character) return ''; | 3253 | if (!character) return ''; |
| 3245 | return baseChatReplace(character.data?.extensions?.depth_prompt?.prompt?.trim(), name1, name2); | 3254 | return baseChatReplace(character.data?.extensions?.depth_prompt?.prompt?.trim()); |
| 3246 | }, | 3255 | }, |
| 3247 | creatorNotes: () => { | 3256 | creatorNotes: () => { |
| 3248 | if (!character) return ''; | 3257 | if (!character) return ''; |
| 3249 | return baseChatReplace(character.data?.creator_notes?.trim(), name1, name2); | 3258 | return baseChatReplace(character.data?.creator_notes?.trim()); |
| 3250 | }, | 3259 | }, |
| 3251 | // These four fields may be overridden by group cards | 3260 | // These four fields may be overridden by group cards |
| 3252 | description: () => { | 3261 | description: () => { |
| 3253 | if (groupCardsLazy) return groupCardsLazy.description; | 3262 | if (groupCardsLazy) return groupCardsLazy.description; |
| 3254 | if (!character) return ''; | 3263 | if (!character) return ''; |
| 3255 | return baseChatReplace(character.description?.trim(), name1, name2); | 3264 | return baseChatReplace(character.description?.trim()); |
| 3256 | }, | 3265 | }, |
| 3257 | personality: () => { | 3266 | personality: () => { |
| 3258 | if (groupCardsLazy) return groupCardsLazy.personality; | 3267 | if (groupCardsLazy) return groupCardsLazy.personality; |
| 3259 | if (!character) return ''; | 3268 | if (!character) return ''; |
| 3260 | return baseChatReplace(character.personality?.trim(), name1, name2); | 3269 | return baseChatReplace(character.personality?.trim()); |
| 3261 | }, | 3270 | }, |
| 3262 | scenario: () => { | 3271 | scenario: () => { |
| 3263 | if (groupCardsLazy) return groupCardsLazy.scenario; | 3272 | if (groupCardsLazy) return groupCardsLazy.scenario; |
| 3264 | if (!character) return ''; | 3273 | if (!character) return ''; |
| 3265 | const scenarioText = chat_metadata['scenario'] || character.scenario || ''; | 3274 | const scenarioText = chat_metadata['scenario'] || character.scenario || ''; |
| 3266 | return baseChatReplace(scenarioText.trim(), name1, name2); | 3275 | return baseChatReplace(scenarioText.trim()); |
| 3267 | }, | 3276 | }, |
| 3268 | mesExamples: () => { | 3277 | mesExamples: () => { |
| 3269 | if (groupCardsLazy) return groupCardsLazy.mesExamples; | 3278 | if (groupCardsLazy) return groupCardsLazy.mesExamples; |
| 3270 | if (!character) return ''; | 3279 | if (!character) return ''; |
| 3271 | const exampleDialog = chat_metadata['mes_example'] || character.mes_example || ''; | 3280 | const exampleDialog = chat_metadata['mes_example'] || character.mes_example || ''; |
| 3272 | return baseChatReplace(exampleDialog.trim(), name1, name2); | 3281 | return baseChatReplace(exampleDialog.trim()); |
| 3273 | }, | 3282 | }, |
| 3274 | }; | 3283 | }; |
| 3275 | 3284 | ||
| @@ -4404,7 +4413,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4404 | continue; | 4413 | continue; |
| 4405 | } | 4414 | } |
| 4406 | 4415 | ||
| 4407 | const formattedExample = baseChatReplace(exampleMessage, name1, name2); | 4416 | const formattedExample = baseChatReplace(exampleMessage); |
| 4408 | const cleanedExample = parseMesExamples(formattedExample, isInstruct); | 4417 | const cleanedExample = parseMesExamples(formattedExample, isInstruct); |
| 4409 | 4418 | ||
| 4410 | // Insert depending on before or after position | 4419 | // Insert depending on before or after position |
| @@ -4448,9 +4457,9 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4448 | if (main_api !== 'openai') { | 4457 | if (main_api !== 'openai') { |
| 4449 | if (power_user.sysprompt.enabled) { | 4458 | if (power_user.sysprompt.enabled) { |
| 4450 | system = power_user.prefer_character_prompt && system | 4459 | system = power_user.prefer_character_prompt && system |
| 4451 | ? substituteParams(system, name1, name2, (power_user.sysprompt.content ?? '')) | 4460 | ? substituteParams(system, { original: power_user.sysprompt.content ?? '' }) |
| 4452 | : baseChatReplace(power_user.sysprompt.content, name1, name2); | 4461 | : baseChatReplace(power_user.sysprompt.content); |
| 4453 | system = isInstruct ? substituteParams(system, name1, name2, power_user.sysprompt.content) : system; | 4462 | system = isInstruct ? substituteParams(system, { original: power_user.sysprompt.content ?? '' }) : system; |
| 4454 | } else { | 4463 | } else { |
| 4455 | // Nullify if it's not enabled | 4464 | // Nullify if it's not enabled |
| 4456 | system = ''; | 4465 | system = ''; |
| @@ -4508,8 +4517,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4508 | 4517 | ||
| 4509 | if (main_api !== 'openai' && power_user.sysprompt.enabled) { | 4518 | if (main_api !== 'openai' && power_user.sysprompt.enabled) { |
| 4510 | jailbreak = power_user.prefer_character_jailbreak && jailbreak | 4519 | jailbreak = power_user.prefer_character_jailbreak && jailbreak |
| 4511 | ? substituteParams(jailbreak, name1, name2, (power_user.sysprompt.post_history ?? '')) | 4520 | ? substituteParams(jailbreak, { original: power_user.sysprompt.post_history ?? '' }) |
| 4512 | : baseChatReplace(power_user.sysprompt.post_history, name1, name2); | 4521 | : baseChatReplace(power_user.sysprompt.post_history); |
| 4513 | 4522 | ||
| 4514 | // Only inject the jb if there is one | 4523 | // Only inject the jb if there is one |
| 4515 | if (jailbreak) { | 4524 | if (jailbreak) { |
| @@ -1280,10 +1280,10 @@ class PromptManager { | |||
| 1280 | const preparedPrompt = new Prompt(prompt); | 1280 | const preparedPrompt = new Prompt(prompt); |
| 1281 | 1281 | ||
| 1282 | if (typeof original === 'string') { | 1282 | if (typeof original === 'string') { |
| 1283 | if (0 < groupMembers.length) preparedPrompt.content = substituteParams(prompt.content ?? '', null, null, original, groupMembers.join(', ')); | 1283 | if (0 < groupMembers.length) preparedPrompt.content = substituteParams(prompt.content ?? '', { original, groupOverride: groupMembers.join(', ') }); |
| 1284 | else preparedPrompt.content = substituteParams(prompt.content, null, null, original); | 1284 | else preparedPrompt.content = substituteParams(prompt.content, { original }); |
| 1285 | } else { | 1285 | } else { |
| 1286 | if (0 < groupMembers.length) preparedPrompt.content = substituteParams(prompt.content ?? '', null, null, null, groupMembers.join(', ')); | 1286 | if (0 < groupMembers.length) preparedPrompt.content = substituteParams(prompt.content ?? '', { groupOverride: groupMembers.join(', ') }); |
| 1287 | else preparedPrompt.content = substituteParams(prompt.content); | 1287 | else preparedPrompt.content = substituteParams(prompt.content); |
| 1288 | } | 1288 | } |
| 1289 | 1289 | ||
| @@ -457,7 +457,7 @@ export function runRegexScript(regexScript, rawString, { characterOverride } = { | |||
| 457 | function filterString(rawString, trimStrings, { characterOverride } = {}) { | 457 | function filterString(rawString, trimStrings, { characterOverride } = {}) { |
| 458 | let finalString = rawString; | 458 | let finalString = rawString; |
| 459 | trimStrings.forEach((trimString) => { | 459 | trimStrings.forEach((trimString) => { |
| 460 | const subTrimString = substituteParams(trimString, undefined, characterOverride); | 460 | const subTrimString = substituteParams(trimString, { name2Override: characterOverride }); |
| 461 | finalString = finalString.replaceAll(subTrimString, ''); | 461 | finalString = finalString.replaceAll(subTrimString, ''); |
| 462 | }); | 462 | }); |
| 463 | 463 | ||
| @@ -210,7 +210,7 @@ async function translateIncomingMessage(messageId) { | |||
| 210 | return; | 210 | return; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | const textToTranslate = substituteParams(message.mes, context.name1, message.name); | 213 | const textToTranslate = substituteParams(message.mes, { name2Override: message.name }); |
| 214 | const translation = await translate(textToTranslate, extension_settings.translate.target_language); | 214 | const translation = await translate(textToTranslate, extension_settings.translate.target_language); |
| 215 | message.extra.display_text = translation; | 215 | message.extra.display_text = translation; |
| 216 | 216 | ||
| @@ -238,7 +238,7 @@ async function translateIncomingMessageReasoning(messageId) { | |||
| 238 | return false; | 238 | return false; |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | const textToTranslate = substituteParams(message.extra.reasoning, context.name1, message.name); | 241 | const textToTranslate = substituteParams(message.extra.reasoning, { name2Override: message.name }); |
| 242 | const translation = await translate(textToTranslate, extension_settings.translate.target_language); | 242 | const translation = await translate(textToTranslate, extension_settings.translate.target_language); |
| 243 | message.extra.reasoning_display_text = translation; | 243 | message.extra.reasoning_display_text = translation; |
| 244 | 244 | ||
| @@ -39,8 +39,6 @@ import { | |||
| 39 | setCharacterName, | 39 | setCharacterName, |
| 40 | setEditedMessageId, | 40 | setEditedMessageId, |
| 41 | is_send_press, | 41 | is_send_press, |
| 42 | name1, | ||
| 43 | name2, | ||
| 44 | resetChatState, | 42 | resetChatState, |
| 45 | setSendButtonState, | 43 | setSendButtonState, |
| 46 | getCharacters, | 44 | getCharacters, |
| @@ -459,7 +457,7 @@ export function getGroupDepthPrompts(groupId, characterId) { | |||
| 459 | continue; | 457 | continue; |
| 460 | } | 458 | } |
| 461 | 459 | ||
| 462 | const depthPromptText = baseChatReplace(character.data?.extensions?.depth_prompt?.prompt?.trim(), name1, character.name) || ''; | 460 | const depthPromptText = baseChatReplace(character.data?.extensions?.depth_prompt?.prompt?.trim(), null, character.name) || ''; |
| 463 | const depthPromptDepth = character.data?.extensions?.depth_prompt?.depth ?? depth_prompt_depth_default; | 461 | const depthPromptDepth = character.data?.extensions?.depth_prompt?.depth ?? depth_prompt_depth_default; |
| 464 | const depthPromptRole = character.data?.extensions?.depth_prompt?.role ?? depth_prompt_role_default; | 462 | const depthPromptRole = character.data?.extensions?.depth_prompt?.role ?? depth_prompt_role_default; |
| 465 | 463 | ||
| @@ -517,7 +515,7 @@ export function getGroupCharacterCardsLazy(groupId, characterId) { | |||
| 517 | if (!value) return ''; | 515 | if (!value) return ''; |
| 518 | value = value.replace(/<FIELDNAME>/gi, fieldName); | 516 | value = value.replace(/<FIELDNAME>/gi, fieldName); |
| 519 | value = trim ? value.trim() : value; | 517 | value = trim ? value.trim() : value; |
| 520 | return baseChatReplace(value, name1, characterName); | 518 | return baseChatReplace(value, null, characterName); |
| 521 | } | 519 | } |
| 522 | 520 | ||
| 523 | /** | 521 | /** |
| @@ -543,7 +541,7 @@ export function getGroupCharacterCardsLazy(groupId, characterId) { | |||
| 543 | /** | 541 | /** |
| 544 | * Collects and joins field values from all group members | 542 | * Collects and joins field values from all group members |
| 545 | * @param {string} fieldName Display name of the field | 543 | * @param {string} fieldName Display name of the field |
| 546 | * @param {function(import('../script.js').Character): string} getter Function to get field value from character | 544 | * @param {function(Character): string} getter Function to get field value from character |
| 547 | * @param {function(string): string} [preprocess] Optional preprocess function | 545 | * @param {function(string): string} [preprocess] Optional preprocess function |
| 548 | * @returns {string} Combined field values | 546 | * @returns {string} Combined field values |
| 549 | */ | 547 | */ |
| @@ -567,8 +565,8 @@ export function getGroupCharacterCardsLazy(groupId, characterId) { | |||
| 567 | return createLazyFields({ | 565 | return createLazyFields({ |
| 568 | description: () => collectField('Description', c => c.description), | 566 | description: () => collectField('Description', c => c.description), |
| 569 | personality: () => collectField('Personality', c => c.personality), | 567 | personality: () => collectField('Personality', c => c.personality), |
| 570 | scenario: () => baseChatReplace(scenarioOverride?.trim(), name1, name2) || collectField('Scenario', c => c.scenario), | 568 | scenario: () => baseChatReplace(scenarioOverride?.trim()) || collectField('Scenario', c => c.scenario), |
| 571 | mesExamples: () => baseChatReplace(mesExamplesOverride?.trim(), name1, name2) || | 569 | mesExamples: () => baseChatReplace(mesExamplesOverride?.trim()) || |
| 572 | collectField('Example Messages', c => c.mes_example, x => !x.startsWith('<START>') ? `<START>\n${x}` : x), | 570 | collectField('Example Messages', c => c.mes_example, x => !x.startsWith('<START>') ? `<START>\n${x}` : x), |
| 573 | }); | 571 | }); |
| 574 | } | 572 | } |
| @@ -602,7 +600,7 @@ async function getFirstCharacterMessage(character) { | |||
| 602 | mes['original_avatar'] = character.avatar; | 600 | mes['original_avatar'] = character.avatar; |
| 603 | mes['extra'] = { 'gen_id': Date.now() * Math.random() * 1000000 }; | 601 | mes['extra'] = { 'gen_id': Date.now() * Math.random() * 1000000 }; |
| 604 | mes['mes'] = messageText | 602 | mes['mes'] = messageText |
| 605 | ? substituteParams(messageText.trim(), name1, character.name) | 603 | ? substituteParams(messageText.trim(), { name2Override: character.name }) |
| 606 | : ''; | 604 | : ''; |
| 607 | mes['force_avatar'] = | 605 | mes['force_avatar'] = |
| 608 | character.avatar != 'none' | 606 | character.avatar != 'none' |
| @@ -436,10 +436,10 @@ export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvata | |||
| 436 | let suffix = getSuffix() || ''; | 436 | let suffix = getSuffix() || ''; |
| 437 | 437 | ||
| 438 | if (instruct.macro) { | 438 | if (instruct.macro) { |
| 439 | prefix = substituteParams(prefix, name1, name2); | 439 | prefix = substituteParams(prefix, { name1Override: name1, name2Override: name2 }); |
| 440 | prefix = prefix.replace(/{{name}}/gi, name || 'System'); | 440 | prefix = prefix.replace(/{{name}}/gi, name || 'System'); |
| 441 | 441 | ||
| 442 | suffix = substituteParams(suffix, name1, name2); | 442 | suffix = substituteParams(suffix, { name1Override: name1, name2Override: name2 }); |
| 443 | suffix = suffix.replace(/{{name}}/gi, name || 'System'); | 443 | suffix = suffix.replace(/{{name}}/gi, name || 'System'); |
| 444 | } | 444 | } |
| 445 | 445 | ||
| @@ -524,10 +524,10 @@ export function formatInstructModeExamples(mesExamplesArray, name1, name2) { | |||
| 524 | let outputSuffix = power_user.instruct.output_suffix || ''; | 524 | let outputSuffix = power_user.instruct.output_suffix || ''; |
| 525 | 525 | ||
| 526 | if (power_user.instruct.macro) { | 526 | if (power_user.instruct.macro) { |
| 527 | inputPrefix = substituteParams(inputPrefix, name1, name2); | 527 | inputPrefix = substituteParams(inputPrefix, { name1Override: name1, name2Override: name2 }); |
| 528 | outputPrefix = substituteParams(outputPrefix, name1, name2); | 528 | outputPrefix = substituteParams(outputPrefix, { name1Override: name1, name2Override: name2 }); |
| 529 | inputSuffix = substituteParams(inputSuffix, name1, name2); | 529 | inputSuffix = substituteParams(inputSuffix, { name1Override: name1, name2Override: name2 }); |
| 530 | outputSuffix = substituteParams(outputSuffix, name1, name2); | 530 | outputSuffix = substituteParams(outputSuffix, { name1Override: name1, name2Override: name2 }); |
| 531 | 531 | ||
| 532 | inputPrefix = inputPrefix.replace(/{{name}}/gi, name1); | 532 | inputPrefix = inputPrefix.replace(/{{name}}/gi, name1); |
| 533 | outputPrefix = outputPrefix.replace(/{{name}}/gi, name2); | 533 | outputPrefix = outputPrefix.replace(/{{name}}/gi, name2); |
| @@ -631,7 +631,7 @@ export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, | |||
| 631 | } | 631 | } |
| 632 | 632 | ||
| 633 | if (instruct.macro) { | 633 | if (instruct.macro) { |
| 634 | sequence = substituteParams(sequence, name1, name2); | 634 | sequence = substituteParams(sequence, { name1Override: name1, name2Override: name2 }); |
| 635 | sequence = sequence.replace(/{{name}}/gi, name || 'System'); | 635 | sequence = sequence.replace(/{{name}}/gi, name || 'System'); |
| 636 | } | 636 | } |
| 637 | 637 | ||