Aller au contenu

PM Scripts

Tech term: Unsafe Scripts

PM Scripts (Prompt Manager Scripts) sont des extension-level scripts écrits directement dans Prompt Manager pour les scènes interactives.

Ils s’exécutent dans le navigateur pendant qu’un chat est ouvert et peuvent utiliser les TavernAI APIs pour events, UI, storage et chat state.

Utilisez-les quand vous devez ajouter des panneaux personnalisés à l’interface, des live indicators, un état par réponse ou une logique interactive.

Prompt Manager Scripts fonctionnent dans le navigateur

Section intitulée « Prompt Manager Scripts fonctionnent dans le navigateur »

PM Scripts sont des script items dans Prompt Manager qui s’exécutent dans le navigateur quand un chat est ouvert.

Ils réagissent aux chat events, rendent de l’UI et sauvegardent l’état entre les sessions.

Leur rôle est le comportement interactif autour du chat. La construction du prompt appartient au prompt text et aux Macros.

Utilisez PM Scripts quand la logique appartient à la live chat session, pas au texte du prompt lui-même.

Adapté pour :

  • UI panels et indicators;
  • custom AI games et playable scenes;
  • scene helpers liés à l’activité du chat;
  • custom message decorations;
  • event-driven logic après la fin de la génération;
  • état qui doit se mettre à jour pendant que le chat est ouvert;
  • comportement per-chat ou per-reply dans le navigateur.

PM Scripts démarrent quand un chat s’ouvre et s’arrêtent quand le chat se ferme ou change.

Chaque script s’exécute dans son propre scope isolé. Les variables locales restent dans ce script, sauf si vous utilisez explicitement shared storage.

Le pattern propre est :

  • root code enregistre les handlers;
  • event handlers font le travail principal;
  • chat.load gère l’async setup et le chargement de l’état initial.

Root code reste petit, et la chat-driven logic vit dans event handlers.

PM Scripts s’abonnent aux chat events avec TAI.on(event, handler).

EventQuand il se déclenche
chat.loadLe chat est ouvert et tous les scripts sont initialisés. Utilisez-le pour async setup et chargement de l’état initial.
chat.unloadLe chat se ferme ou change. Utilisez-le pour sauvegarder l’état final.
chat.message.createdUn nouveau message a été créé. Payload: { messageId, origin, text, activeContentId }
chat.message.selectedLe message actif dans une branche a changé. Payload: { messageId }
chat.message.deletedUn message a été supprimé.
chat.message.content.selectedLe content actif dans un message a changé. Payload: { messageId, previousContentId, contentId }
chat.message.content.deletedUn message content record a été supprimé.
chat.message.content.version.selectedLa content version active a changé. Payload: { messageId, contentId, versionId }
chat.message.generation.startedLa génération commence. Payload: { chatId }
chat.message.generation.chunkUn streaming chunk a été reçu. Payload: { contentId, text, blockType }
chat.message.generation.completedLa génération est terminée. Payload: { contentId, text, finishReason }
chat.message.generation.failedLa génération a échoué.
chat.ActiveBranchPath.changedLe chemin actif a changé (high-level hook pour la plupart des UI scripts). Payload: { reason, changedMessageId, changedContentId, activeLeafMessageId, activeLeafContentId, branchPath } (branchPath peut être partiel ou vide)

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

Les handlers peuvent être async. Utilisez TAI.once(event, handler) quand un handler ne doit s’exécuter qu’une seule fois.

Les deux stores sont persistants : ils survivent à la fermeture et à la réouverture du chat. La différence est dans le scope.

TAI.store.chat garde une valeur par clé pour tout le chat.

Adapté pour un état sans historique séparé par branches : settings, toggles, metadata qui appartiennent au chat complet, pas à un chemin précis de la conversation.

TAI.store.message.content garde des données sur un message content précis.

Un message est une position dans le chat. Son content est la reply variant active dans ce message. Quand un message a plusieurs content swipes, chaque content record peut avoir ses propres stored data.

Adapté pour les données produites par une réponse générée : parsed damage, label, roll result, score ou UI state appartenant exactement à ce texte de réponse.

Utilisez TAI.store.chat pour l’état de tout le chat. Utilisez TAI.store.message.content quand la valeur appartient à un reply content précis.

PM Scripts peuvent rendre de la scene UI dans TAI.ui.container.

Ils peuvent aussi enregistrer des message content decorators quand l’UI appartient avant ou après un message content précis.

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

Utilisez TAI.ui.showNotification(message, type) pour de petites 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>`;
}

La valeur HP est sauvegardée sur le content de la réponse générée. Quand l’active content change, le script charge le HP lié exactement à ce content record.

PM Scripts et Macros travaillent souvent ensemble, mais appartiennent à des couches différentes.

  • s’exécutent sur le serveur;
  • affectent le prompt text;
  • s’exécutent pendant prompt building.
  • s’exécutent dans le navigateur;
  • réagissent aux chat events;
  • affectent l’UI et l’interactive behavior.

Ils peuvent partager un état via TAI.store.chat. Un script peut mettre à jour chat storage dans le navigateur, puis une Macro peut lire cette valeur pendant une génération ultérieure.

PM Scripts sont du JavaScript actif exécuté dans le navigateur. Traitez PM Scripts comme des extensions : activez seulement les scripts provenant de sources auxquelles vous faites confiance et que vous comprenez.

Les PM Scripts importés passent par plusieurs safety gates avant de pouvoir s’exécuter.

  • Les packs avec scripts peuvent être bloqués à l’importation par server policy.
  • Les scripts importés sont marqués par le serveur comme imported.
  • Les scripts importés peuvent être marqués unapproved et doivent être approved avant activation.
  • L’exécution de scripts importés peut être désactivée par server policy.
  • L’édition du code d’un script importé peut être désactivée par server policy.

Ces policies viennent de config.yaml et sont disponibles depuis l’UI de l’application en lecture seule.

Pratique :

  • vérifiez les scripts importés avant de les activer;
  • gardez la scene-specific logic petite et lisible;
  • sauvegardez shared state explicitement au lieu de le cacher dans des variables locales;
  • utilisez Macros quand la tâche appartient au prompt text ou au post-generation text cleanup.