Ir al contenido

PM Scripts

Tech term: Unsafe Scripts

PM Scripts (Prompt Manager Scripts) son extension-level scripts escritos directamente en Prompt Manager para escenas interactivas.

Se ejecutan en el navegador mientras el chat está abierto y pueden usar TavernAI APIs para events, UI, storage y chat state.

Úsalos cuando necesites agregar paneles personalizados a la interfaz, live indicators, estado por respuesta o lógica interactiva.

Prompt Manager Scripts funcionan en el navegador

Sección titulada «Prompt Manager Scripts funcionan en el navegador»

PM Scripts son script items dentro de Prompt Manager que se ejecutan en el navegador cuando un chat está abierto.

Reaccionan a chat events, renderizan UI y guardan estado entre sesiones.

Su trabajo es el comportamiento interactivo alrededor del chat. La construccion del prompt pertenece a prompt text y Macros.

Usa PM Scripts cuando la lógica pertenece a la live chat session, no al texto del prompt en sí.

Encajan para:

  • UI panels e indicators;
  • custom AI games y playable scenes;
  • scene helpers vinculados a la actividad del chat;
  • custom message decorations;
  • event-driven logic después de que termina la generación;
  • estado que debe actualizarse mientras el chat está abierto;
  • comportamiento per-chat o per-reply en el navegador.

PM Scripts empiezan cuando se abre un chat y se detienen cuando el chat se cierra o cambia.

Cada script se ejecuta en su propio scope aislado. Las variables locales permanecen dentro de ese script, salvo que uses shared storage de forma explícita.

El patrón limpio es:

  • root code registra handlers;
  • event handlers hacen el trabajo principal;
  • chat.load se encarga del async setup y de cargar el estado inicial.

Root code se mantiene pequeño, y la chat-driven logic vive en event handlers.

PM Scripts se suscriben a chat events con TAI.on(event, handler).

EventCuándo se dispara
chat.loadEl chat está abierto y todos los scripts están inicializados. Úsalo para async setup y carga de estado inicial.
chat.unloadEl chat se está cerrando o cambiando. Úsalo para guardar estado final.
chat.message.createdSe creó un mensaje nuevo. Payload: { messageId, origin, text, activeContentId }
chat.message.selectedCambió el mensaje activo en una rama. Payload: { messageId }
chat.message.deletedSe eliminó un mensaje.
chat.message.content.selectedCambió el content activo dentro de un mensaje. Payload: { messageId, previousContentId, contentId }
chat.message.content.deletedSe eliminó un message content record.
chat.message.content.version.selectedCambió la content version activa. Payload: { messageId, contentId, versionId }
chat.message.generation.startedEmpezó la generación. Payload: { chatId }
chat.message.generation.chunkSe recibió un streaming chunk. Payload: { contentId, text, blockType }
chat.message.generation.completedLa generación terminó. Payload: { contentId, text, finishReason }
chat.message.generation.failedLa generación falló.
chat.ActiveBranchPath.changedCambió el camino activo (high-level hook para la mayoría de UI scripts). Payload: { reason, changedMessageId, changedContentId, activeLeafMessageId, activeLeafContentId, branchPath } (branchPath puede ser parcial o estar vacío)

Valores de finishReason: "stop", "length", "content_filter", "cancelled", "error".

Los handlers pueden ser async. Usa TAI.once(event, handler) cuando un handler debe ejecutarse solo una vez.

Ambos stores son persistentes: se conservan después de cerrar y volver a abrir el chat. La diferencia está en el scope.

TAI.store.chat guarda un valor por clave para todo el chat.

Encaja para estado que no tiene historial separado por ramas: settings, toggles, metadata que pertenecen al chat completo, no a un camino concreto de la conversación.

TAI.store.message.content guarda datos en un message content concreto.

Un mensaje es una posición en el chat. Su content es la reply variant activa dentro de ese mensaje. Cuando un mensaje tiene varios content swipes, cada content record puede tener sus propios stored data.

Encaja para datos producidos por una respuesta generada: parsed damage, label, roll result, score o UI state que pertenece exactamente a ese texto de respuesta.

Usa TAI.store.chat para estado de todo el chat. Usa TAI.store.message.content cuando el valor pertenece a un reply content concreto.

PM Scripts pueden renderizar scene UI en TAI.ui.container.

También pueden registrar message content decorators cuando el UI pertenece antes o después de un message content concreto.

TAI.ui.container.innerHTML = `<div>Scene state: active</div>`;

Usa TAI.ui.showNotification(message, type) para pequeñas scene notifications.

let hp = 100;
TAI.on("chat.load", () => {
render();
// chat.ActiveBranchPath.changed fires shortly after and loads the correct value
});
TAI.on("chat.message.generation.completed", async (msg) => {
const damage = parseDamage(msg.text);
if (damage) {
hp = Math.max(0, hp - damage);
}
// Store HP on this specific swipe so branching reads the right value
await TAI.store.message.content.set(msg.contentId, "hp", hp);
render();
});
TAI.on("chat.ActiveBranchPath.changed", async (data) => {
if (!data.activeLeafContentId) return;
// Load HP from the current active leaf content
hp = (await TAI.store.message.content.get(data.activeLeafContentId, "hp")) ?? 100;
render();
});
function render() {
TAI.ui.container.innerHTML = `<div>HP: ${hp}</div>`;
}

El valor HP se guarda en el content de la respuesta generada. Cuando cambia el active content, el script carga el HP vinculado exactamente a ese content record.

PM Scripts y Macros suelen trabajar juntos, pero pertenecen a capas distintas.

  • se ejecutan en el servidor;
  • afectan al prompt text;
  • se ejecutan durante prompt building.
  • se ejecutan en el navegador;
  • reaccionan a chat events;
  • afectan al UI y al interactive behavior.

Pueden compartir estado mediante TAI.store.chat. Un script puede actualizar chat storage en el navegador, y luego un Macro puede leer ese valor durante una generación posterior.

PM Scripts son JavaScript activo que se ejecuta en el navegador. Trata PM Scripts como extensions: activa solo scripts de fuentes en las que confíes y que entiendas.

Los PM Scripts importados pasan por varias safety gates antes de poder ejecutarse.

  • Packs con scripts pueden ser bloqueados durante la importación por server policy.
  • Los scripts importados son marcados por el servidor como imported.
  • Los scripts importados pueden marcarse como unapproved y deben ser approved antes de activarse.
  • La ejecución de scripts importados puede desactivarse por server policy.
  • La edición del código de un script importado puede desactivarse por server policy.

Estas policies vienen de config.yaml y están disponibles desde el UI de la aplicación solo en modo lectura.

Practica:

  • revisa los scripts importados antes de activarlos;
  • mantén la scene-specific logic pequeña y legible;
  • guarda shared state de forma explicita en lugar de esconderlo en variables locales;
  • usa Macros cuando la tarea pertenece a prompt text o post-generation text cleanup.