Blame Raw
Cohee · e3f41666 · · 205 lines (8.3 KB)
1 contributor
1import { MacroRegistry, MacroCategory, MacroValueType } from '../engine/MacroRegistry.js';
2import { isMobile } from '../../RossAscends-mods.js';
3import { parseMesExamples, main_api } from '../../../script.js';
4import { power_user } from '../../power-user.js';
5import { formatInstructModeExamples } from '../../instruct-mode.js';
6
7/** @typedef {import('../engine/MacroEnv.types.js').MacroEnv} MacroEnv */
8
9/**
10 * Registers macros that mostly act as simple accessors to MacroEnv fields
11 * (names, character card fields, system metadata, extras) or basic
12 * environment flags.
13 */
14export function registerEnvMacros() {
15 // Names and participant macros (from MacroEnv.names)
16 MacroRegistry.registerMacro('user', {
17 category: MacroCategory.NAMES,
18 description: 'Your current Persona username.',
19 returns: 'Persona username.',
20 handler: ({ env }) => env.names.user,
21 });
22
23 MacroRegistry.registerMacro('char', {
24 category: MacroCategory.NAMES,
25 description: 'The character\'s name.',
26 returns: 'Character name.',
27 handler: ({ env }) => env.names.char,
28 });
29
30 MacroRegistry.registerMacro('group', {
31 aliases: [{ alias: 'charIfNotGroup', visible: false }],
32 category: MacroCategory.NAMES,
33 description: 'Comma-separated list of group member names (including muted) or the character name in solo chats.',
34 returns: 'List of group member names.',
35 handler: ({ env }) => env.names.group ?? '',
36 });
37
38 MacroRegistry.registerMacro('groupNotMuted', {
39 category: MacroCategory.NAMES,
40 description: 'Comma-separated list of group member names excluding muted members.',
41 returns: 'List of group member names excluding muted members.',
42 handler: ({ env }) => env.names.groupNotMuted ?? '',
43 });
44
45 MacroRegistry.registerMacro('notChar', {
46 category: MacroCategory.NAMES,
47 description: 'Comma-separated list of all participants except the current speaker.',
48 returns: 'List of all participants except the current speaker.',
49 handler: ({ env }) => env.names.notChar ?? '',
50 });
51
52 // Character card field macros (from MacroEnv.character)
53 MacroRegistry.registerMacro('charPrompt', {
54 category: MacroCategory.CHARACTER,
55 description: 'The character\'s Main Prompt override.',
56 returns: 'Character Main Prompt override.',
57 handler: ({ env }) => env.character.charPrompt ?? '',
58 });
59
60 MacroRegistry.registerMacro('charInstruction', {
61 category: MacroCategory.CHARACTER,
62 description: 'The character\'s Post-History Instructions override.',
63 returns: 'Character Post-History Instructions override.',
64 handler: ({ env }) => env.character.charInstruction ?? '',
65 });
66
67 MacroRegistry.registerMacro('charDescription', {
68 aliases: [{ alias: 'description' }],
69 category: MacroCategory.CHARACTER,
70 description: 'The character\'s description.',
71 returns: 'Character description.',
72 handler: ({ env }) => env.character.description ?? '',
73 });
74
75 MacroRegistry.registerMacro('charPersonality', {
76 aliases: [{ alias: 'personality' }],
77 category: MacroCategory.CHARACTER,
78 description: 'The character\'s personality.',
79 returns: 'Character personality.',
80 handler: ({ env }) => env.character.personality ?? '',
81 });
82
83 MacroRegistry.registerMacro('charScenario', {
84 aliases: [{ alias: 'scenario' }],
85 category: MacroCategory.CHARACTER,
86 description: 'The character\'s scenario.',
87 returns: 'Character scenario.',
88 handler: ({ env }) => env.character.scenario ?? '',
89 });
90
91 MacroRegistry.registerMacro('persona', {
92 category: MacroCategory.CHARACTER,
93 description: 'Your current Persona description.',
94 returns: 'Persona description.',
95 handler: ({ env }) => env.character.persona ?? '',
96 });
97
98 MacroRegistry.registerMacro('mesExamplesRaw', {
99 category: MacroCategory.CHARACTER,
100 description: 'Unformatted dialogue examples from the character card.',
101 returns: 'Unformatted dialogue examples.',
102 handler: ({ env }) => env.character.mesExamplesRaw ?? '',
103 });
104
105 MacroRegistry.registerMacro('mesExamples', {
106 category: MacroCategory.CHARACTER,
107 description: 'The character\'s dialogue examples, formatted for instruct mode when enabled.',
108 returns: 'Formatted dialogue examples.',
109 handler: ({ env }) => {
110 const raw = env.character.mesExamplesRaw ?? '';
111 if (!raw) return '';
112
113 const isInstruct = !!power_user?.instruct?.enabled && main_api !== 'openai';
114 const parsed = parseMesExamples(raw, isInstruct);
115
116 if (!Array.isArray(parsed) || parsed.length === 0) {
117 return '';
118 }
119 if (!isInstruct) {
120 return parsed.join('');
121 }
122
123 const formatted = formatInstructModeExamples(parsed, env.names.user, env.names.char);
124 return Array.isArray(formatted) ? formatted.join('') : '';
125 },
126 });
127
128 MacroRegistry.registerMacro('charDepthPrompt', {
129 category: MacroCategory.CHARACTER,
130 description: 'The character\'s @ Depth Note.',
131 returns: 'Character @ Depth Note.',
132 handler: ({ env }) => env.character.charDepthPrompt ?? '',
133 });
134
135 MacroRegistry.registerMacro('charCreatorNotes', {
136 aliases: [{ alias: 'creatorNotes' }],
137 category: MacroCategory.CHARACTER,
138 description: 'Creator notes from the character card.',
139 returns: 'Creator notes.',
140 handler: ({ env }) => env.character.creatorNotes ?? '',
141 });
142
143 MacroRegistry.registerMacro('charFirstMessage', {
144 aliases: [{ alias: 'greeting' }],
145 category: MacroCategory.CHARACTER,
146 unnamedArgs: [
147 {
148 name: 'index',
149 optional: true,
150 defaultValue: '0',
151 type: MacroValueType.INTEGER,
152 description: '0-based index. 0 (default) returns the main greeting, 1 and up return alternate greetings.',
153 },
154 ],
155 description: 'The character\'s first message / greeting. Optionally specify an index to access alternate greetings.',
156 returns: 'Character greeting at the given index, or empty string if out of bounds.',
157 exampleUsage: ['{{greeting}}', '{{greeting::0}}', '{{greeting::1}}'],
158 handler: ({ env, unnamedArgs: [index] }) => {
159 const i = Number(index ?? 0);
160 if (i === 0) return env.character.firstMessage ?? '';
161 const altGreetings = env.character.alternateGreetings;
162 if (!Array.isArray(altGreetings)) return '';
163 return altGreetings[i - 1] ?? '';
164 },
165 });
166
167 // Character version macros (legacy variants and documented {{charVersion}})
168 MacroRegistry.registerMacro('charVersion', {
169 aliases: [
170 { alias: 'version', visible: false }, // Legacy alias
171 { alias: 'char_version', visible: false }, // Legacy underscore variant
172 ],
173 category: MacroCategory.CHARACTER,
174 description: 'The character\'s version number.',
175 returns: 'Character version number.',
176 handler: ({ env }) => env.character.version ?? '',
177 });
178
179 // System / env extras macros (from MacroEnv.system / MacroEnv.extra)
180 MacroRegistry.registerMacro('model', {
181 category: MacroCategory.STATE,
182 description: 'Model name for the currently selected API (Chat Completion or Chat Completion).',
183 returns: 'Model name.',
184 handler: ({ env }) => env.system.model,
185 });
186
187 MacroRegistry.registerMacro('original', {
188 category: MacroCategory.CHARACTER,
189 description: 'Original message content for {{original}} substitution in in character prompt overrides.',
190 returns: 'Original message content.',
191 handler: ({ env }) => {
192 const value = env.functions.original();
193 return value;
194 },
195 });
196
197 // Device / environment macros
198 MacroRegistry.registerMacro('isMobile', {
199 category: MacroCategory.STATE,
200 description: '"true" if currently running in a mobile environment, "false" otherwise.',
201 returns: 'Whether the environment is mobile.',
202 returnType: MacroValueType.BOOLEAN,
203 handler: () => String(isMobile()),
204 });
205}