Implement {{charFirstMessage}} / {{greeting}} macro with alternate greeting indexing and substitution (#5220)
* Initial plan
* Implement {{firstMessage}} / {{greeting}} macro for character's first message
Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
* Simplify firstMessage resolver to use || instead of ?? for consistency
Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
* Remove {{firstMessage}} alias, add 0-based greeting index for alternate greetings
Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
* Add alternateGreetings to env, apply substitution to greetings
Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
* Remove legacy greeting macro, keep only new engine implementation
Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Cohee1207 <18619528+Cohee1207@users.noreply.github.com>
Co-authored-by: anthropic-code-agent[bot] <242468646+Claude@users.noreply.github.com>
This commit is contained in:
@@ -3230,6 +3230,8 @@ export function baseChatReplace(value, name1Override = null, name2Override = nul
|
|||||||
* @property {string} version Character version
|
* @property {string} version Character version
|
||||||
* @property {string} charDepthPrompt Character depth note
|
* @property {string} charDepthPrompt Character depth note
|
||||||
* @property {string} creatorNotes Character creator notes
|
* @property {string} creatorNotes Character creator notes
|
||||||
|
* @property {string} firstMessage Character first message / greeting
|
||||||
|
* @property {string[]} alternateGreetings Character alternate greetings
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3316,6 +3318,17 @@ export function getCharacterCardFieldsLazy({ chid = undefined } = {}) {
|
|||||||
const exampleDialog = chat_metadata.mes_example || character.mes_example || '';
|
const exampleDialog = chat_metadata.mes_example || character.mes_example || '';
|
||||||
return baseChatReplace(exampleDialog.trim());
|
return baseChatReplace(exampleDialog.trim());
|
||||||
},
|
},
|
||||||
|
firstMessage: () => {
|
||||||
|
if (!character) return '';
|
||||||
|
const firstMes = character.first_mes?.trim() || '';
|
||||||
|
return baseChatReplace(firstMes);
|
||||||
|
},
|
||||||
|
alternateGreetings: () => {
|
||||||
|
if (!character) return [];
|
||||||
|
const altGreetings = character.data?.alternate_greetings;
|
||||||
|
if (!Array.isArray(altGreetings)) return [];
|
||||||
|
return altGreetings.map(greeting => baseChatReplace(greeting?.trim()));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return createLazyFields(resolvers);
|
return createLazyFields(resolvers);
|
||||||
@@ -3342,6 +3355,8 @@ export function getCharacterCardFields({ chid = undefined } = {}) {
|
|||||||
version: lazy.version,
|
version: lazy.version,
|
||||||
charDepthPrompt: lazy.charDepthPrompt,
|
charDepthPrompt: lazy.charDepthPrompt,
|
||||||
creatorNotes: lazy.creatorNotes,
|
creatorNotes: lazy.creatorNotes,
|
||||||
|
firstMessage: lazy.firstMessage,
|
||||||
|
alternateGreetings: lazy.alternateGreetings,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,6 +140,30 @@ export function registerEnvMacros() {
|
|||||||
handler: ({ env }) => env.character.creatorNotes ?? '',
|
handler: ({ env }) => env.character.creatorNotes ?? '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
MacroRegistry.registerMacro('charFirstMessage', {
|
||||||
|
aliases: [{ alias: 'greeting' }],
|
||||||
|
category: MacroCategory.CHARACTER,
|
||||||
|
unnamedArgs: [
|
||||||
|
{
|
||||||
|
name: 'index',
|
||||||
|
optional: true,
|
||||||
|
defaultValue: '0',
|
||||||
|
type: MacroValueType.INTEGER,
|
||||||
|
description: '0-based index. 0 (default) returns the main greeting, 1 and up return alternate greetings.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
description: 'The character\'s first message / greeting. Optionally specify an index to access alternate greetings.',
|
||||||
|
returns: 'Character greeting at the given index, or empty string if out of bounds.',
|
||||||
|
exampleUsage: ['{{greeting}}', '{{greeting::0}}', '{{greeting::1}}'],
|
||||||
|
handler: ({ env, unnamedArgs: [index] }) => {
|
||||||
|
const i = Number(index ?? 0);
|
||||||
|
if (i === 0) return env.character.firstMessage ?? '';
|
||||||
|
const altGreetings = env.character.alternateGreetings;
|
||||||
|
if (!Array.isArray(altGreetings)) return '';
|
||||||
|
return altGreetings[i - 1] ?? '';
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// Character version macros (legacy variants and documented {{charVersion}})
|
// Character version macros (legacy variants and documented {{charVersion}})
|
||||||
MacroRegistry.registerMacro('charVersion', {
|
MacroRegistry.registerMacro('charVersion', {
|
||||||
aliases: [
|
aliases: [
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
* @property {string} [charDepthPrompt]
|
* @property {string} [charDepthPrompt]
|
||||||
* @property {string} [creatorNotes]
|
* @property {string} [creatorNotes]
|
||||||
* @property {string} [version]
|
* @property {string} [version]
|
||||||
|
* @property {string} [firstMessage]
|
||||||
|
* @property {string[]} [alternateGreetings]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -109,10 +109,19 @@ class MacroEnvBuilder {
|
|||||||
['version', 'version'],
|
['version', 'version'],
|
||||||
['charDepthPrompt', 'charDepthPrompt'],
|
['charDepthPrompt', 'charDepthPrompt'],
|
||||||
['creatorNotes', 'creatorNotes'],
|
['creatorNotes', 'creatorNotes'],
|
||||||
|
['firstMessage', 'firstMessage'],
|
||||||
|
['alternateGreetings', 'alternateGreetings'],
|
||||||
]);
|
]);
|
||||||
for (const [envKey, fieldKey] of fieldMappings) {
|
for (const [envKey, fieldKey] of fieldMappings) {
|
||||||
Object.defineProperty(env.character, envKey, {
|
Object.defineProperty(env.character, envKey, {
|
||||||
get() { return fields[fieldKey] || ''; },
|
get() {
|
||||||
|
const value = fields[fieldKey];
|
||||||
|
// alternateGreetings should default to [] instead of ''
|
||||||
|
if (envKey === 'alternateGreetings') {
|
||||||
|
return Array.isArray(value) ? value : [];
|
||||||
|
}
|
||||||
|
return value || '';
|
||||||
|
},
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
configurable: true,
|
configurable: true,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ test.describe('MacroEnvBuilder', () => {
|
|||||||
'version',
|
'version',
|
||||||
'charDepthPrompt',
|
'charDepthPrompt',
|
||||||
'creatorNotes',
|
'creatorNotes',
|
||||||
|
'firstMessage',
|
||||||
|
'alternateGreetings',
|
||||||
]));
|
]));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user