Macros
Tech term: Safe Scripts
Macros позволяют тексту Prompt Manager запускать небольшие JavaScript-фрагменты во время генерации.
Используйте их, когда нужно передать произвольное значение, параметры состояний или изменить результат генерации.
Macros работают в двух фазах
Заголовок раздела «Macros работают в двух фазах»В TavernAI есть две формы Macro, и обе выполняются на сервере.
<% ... %>— pre-gen. Выполняется, пока TavernAI собирает промпт. Вывод становится частью промпта и отправляется в модель.<%% ... %%>— post-gen. Выполняется после получения AI-ответа и может проверять и переписывать generated blocks до показа финального сообщения.
Macros — server-side tools. Если задача относится к live-сцене в браузере, используйте PM Scripts.
Для чего нужны Macros
Заголовок раздела «Для чего нужны Macros»Используйте Macros, когда текст промпта или содержимое сгенерированного сообщения должны меняться динамически, а не оставаться статичными.
Подходят для:
- случайных событий;
- текста, зависящего от времени;
- условных формулировок;
- текста промпта, зависящего от общего состояния;
- постобработки сгенерированного текста;
- состояния чата, которое должно использоваться в следующих генерациях.
Синтаксис Macro
Заголовок раздела «Синтаксис Macro»Pre-gen: <% %>
Заголовок раздела «Pre-gen: <% %>»Pre-gen Macros выполняются во время сборки промпта.
The room feels <% rand(["warm", "cold", "silent"]) %>.Если блок содержит expression, результат вставляется в текст.
Для большего контроля используйте print().
<%print("Turn: ");print((TAI.store.chat.get("turn") || 0) + 1);%>Post-gen: <%% %%>
Заголовок раздела «Post-gen: <%% %%>»Post-gen Macros выполняются после получения AI-ответа. Используйте эту форму, когда ответ нужно изменить после генерации.
<%%for (var i = 0; i < TAI.generated.blocks.length; i++) { var block = TAI.generated.blocks[i]; if (block.type !== "text") continue; block.text = block.text.replace(/OOC:/g, "(OOC:");}%%>Один item, две фазы выполнения
Заголовок раздела «Один item, две фазы выполнения»Все блоки <% %> внутри одного элемента Prompt Manager выполняются по порядку во время сборки промпта.
Блоки <%% %%> из того же item выполняются позже, после генерации.
Не рассчитывайте, что локальные JavaScript variables перейдут из pre-gen в post-gen. Если данные из <% %> должны быть доступны в <%% %%>, запишите их в TAI.vars или TAI.store.chat.
Разные промпты не делят локальные JavaScript variables друг с другом. Если данные должны перейти между промптами, используйте TAI.vars или TAI.store.chat.
Placeholders и Macros
Заголовок раздела «Placeholders и Macros»Placeholders и Macros решают разные задачи.
- placeholders подставляют известные значения контекста;
- Macros вычисляют или собирают текст либо постобрабатывают сгенерированный текст.
Placeholder resolution происходит до выполнения pre-gen Macro. <% %> работает поверх уже разрешенного prompt context.
Блоки <%% %%> никогда не вставляются в промпт, поэтому они вообще не ведут себя как placeholder text.
Используйте справочник плейсхолдеров, когда значение уже есть в контексте. Используйте Macro, когда значение нужно вычислить.
Основные инструменты данных
Заголовок раздела «Основные инструменты данных»TAI.vars
Заголовок раздела «TAI.vars»TAI.vars — общее состояние для одной сборки промпта.
Используйте его, когда одному промпту нужно передать значение другому промпту в той же генерации, или когда блок <% %> должен подготовить данные для последующего блока <%% %%>.
Подходит для:
- случайного броска кубика с повторным использованием;
- вычисления общего значения состояния из последнего сообщения;
- реакции скриптов на один временный результат;
- связи pre-gen и post-gen логики в одном prompt cycle.
<% TAI.vars.set("mood", rand(["tense", "calm", "alert"])) %>Позже в другом item:
Current mood: <% TAI.vars.get("mood") %>Мост из pre-gen в post-gen:
<% TAI.vars.set("target", "OOC:") %>
<%%var target = TAI.vars.get("target");for (var i = 0; i < TAI.generated.blocks.length; i++) { var block = TAI.generated.blocks[i]; if (block.type !== "text") continue; block.text = block.text.replace(new RegExp(target, "g"), "(OOC:");}%%>TAI.store.chat
Заголовок раздела «TAI.store.chat»TAI.store.chat — состояние, связанное с текущим чатом.
Используйте его, когда значение должно сохраняться между генерациями и после повторного открытия чата.
Подходит для:
- счетчиков ходов;
- RPG-установок;
- флагов сцены;
- значений, записанных сейчас и используемых позже.
<%var turn = TAI.store.chat.get("turn") || 0;turn++;TAI.store.chat.set("turn", turn);print("Turn " + turn);%>TAI.generated
Заголовок раздела «TAI.generated»TAI.generated доступен в блоках <%% %%>.
Используйте его, когда post-gen логика должна читать или переписывать полученное сообщение.
TAI.generated.message.content.blocks — одна часть сгенерированного ответа. Это может быть обычный текст или think блок, и модели могут чередовать типы блоков при создании ответа.
Частые примеры:
TAI.generated.blocks— короткий alias дляTAI.generated.message.content.blocksTAI.generated.message.content.blocks— полный путь к generated content blocksTAI.generated.finishReason
Используйте TAI.generated.blocks, когда нужно переписать сгенерированный текст до того, как финальное сообщение попадет к пользователю.
TAI.chat, TAI.card и TAI.time
Заголовок раздела «TAI.chat, TAI.card и TAI.time»Pre-gen Macros также могут читать structured context напрямую.
Частые примеры:
TAI.chat.messageCountTAI.chat.lastMessageTAI.card.namesTAI.time.hour
Они полезны, когда промпт должен реагировать на текущий разговор, текущих участников или текущее время.
Built-in helpers
Заголовок раздела «Built-in helpers»Macros также открывают небольшой набор helpers для обычной работы с промптами:
print()rand()dice()chance()
Они покрывают большую часть динамического prompt writing без более крупного runtime.
Debug output
Заголовок раздела «Debug output»Используйте TAI.debug.log(...), когда Macro нужен диагностический вывод. Он пишет в backend log/console и не добавляет текст в prompt или generated message.
TAI.debug.log('state', { hp: 10 }, TAI.chat.messageCount);Common patterns
Заголовок раздела «Common patterns»Случайная вариация
Заголовок раздела «Случайная вариация»Используйте Macro, когда повторяющаяся инструкция или описание должны чередоваться между несколькими формами.
Общее состояние на одну генерацию
Заголовок раздела «Общее состояние на одну генерацию»Используйте TAI.vars, когда нескольким промптам в одном промпт менеджере нужно одно общее значение.
Постоянное состояние чата
Заголовок раздела «Постоянное состояние чата»Используйте TAI.store.chat, когда состояние должно сохраняться и влиять на будущие генерации.
Постобработка сгенерированного текста
Заголовок раздела «Постобработка сгенерированного текста»Используйте <%% %%>, когда сгенерированное сообщение нужно переписать после получения, например чтобы нормализовать теги, исправить известные паттерны вывода или применить очистку, специфичную для сцены.
Macros и PM Scripts
Заголовок раздела «Macros и PM Scripts»Macros и PM Scripts находятся на разных слоях.
Используйте Macros, когда
Заголовок раздела «Используйте Macros, когда»- промпту нужно получить текст через
<% %>; - generated message нужно переписать сразу после получения через
<%% %%>; - состояние должно влиять на последующий prompt output или post-processing.
Используйте PM Scripts, когда
Заголовок раздела «Используйте PM Scripts, когда»- логика относится к браузеру;
- script реагирует на chat events в реальном времени;
- результатом является UI behavior, notifications или browser-side interaction.
Если задача — переписать generated blocks до показа финального сообщения, начинайте с post-gen <%% %%>, а не с PM Scripts.
Ограничения
Заголовок раздела «Ограничения»Обе формы Macro выполняются в безопасном server-side sandbox.
Это намеренно узкая среда:
- нет доступа к DOM;
- нет browser APIs;
- нет network fetches;
- нет
eval()илиnew Function(); - нет timer-based browser logic.
Macros остаются в границах prompt-side scripting.
- Справочник карточных плейсхолдеров для простых значений контекста.
- PM Scripts для browser-side logic.