From 0e9f3cbce057a6a9c9b83e94fa1ec227bb5041ba Mon Sep 17 00:00:00 2001 From: kwaroran Date: Fri, 28 Jul 2023 04:42:06 +0900 Subject: [PATCH] [feat] trigger runner --- src/ts/parser.ts | 4 +- src/ts/process/triggers.ts | 138 ++++++++++++++++++++++++++++++++++++- 2 files changed, 138 insertions(+), 4 deletions(-) diff --git a/src/ts/parser.ts b/src/ts/parser.ts index f7fc8636..7b94ef40 100644 --- a/src/ts/parser.ts +++ b/src/ts/parser.ts @@ -679,9 +679,9 @@ export function risuChatParser(da:string, arg:{ return nested[0] + result } -function getVarChat(targetIndex = -1){ +export function getVarChat(targetIndex = -1, chara:character|groupChat = null){ const db = get(DataBase) - const selchar = db.characters[get(selectedCharID)] + const selchar = chara ?? db.characters[get(selectedCharID)] const chat = selchar.chats[selchar.chatPage] let i =0; if(targetIndex === -1 || targetIndex >= chat.message.length){ diff --git a/src/ts/process/triggers.ts b/src/ts/process/triggers.ts index dd878f2f..2e7420a2 100644 --- a/src/ts/process/triggers.ts +++ b/src/ts/process/triggers.ts @@ -1,6 +1,9 @@ +import { getVarChat } from "../parser"; +import type { character } from "../storage/database"; + export interface triggerscript{ comment: string; - type: 'start'|'manual'|'output' + type: 'start'|'manual'|'output'|'input' conditions: triggerCondition[] effect:triggerEffect[] } @@ -24,7 +27,8 @@ export type triggerConditionsExists ={ } export interface triggerEffectSetvar{ - type: 'setvar' + type: 'setvar', + operator: '='|'+='|'-='|'*='|'/=' var:string value:string } @@ -39,4 +43,134 @@ export interface triggerEffectImpersonate{ type: 'impersonate' role: 'user'|'char', value:string +}type triggerMode = 'start'|'manual'|'output'|'input' + +export function runTrigger(char:character,mode:triggerMode){ + let additonalSysPrompt = { + start:'', + historyend: '', + promptend: '' + } + let varValues = getVarChat(-1, char) + let varValuesChanged = false + const triggers = char.triggerscript + const chat = char.chats[char.chatPage] + if(!triggers){ + return {additonalSysPrompt, char} + } + + for(const trigger of triggers){ + if(mode !== trigger.type){ + continue + } + + let pass = true + for(const condition of trigger.conditions){ + if(condition.type === 'var'){ + const varValue = varValues[condition.var] + if(varValue === undefined || varValue === null){ + pass = false + break + } + else{ + if(condition.operator === '='){ + if(varValue !== condition.value){ + pass = false + break + } + } + else if(condition.operator === '!='){ + if(varValue === condition.value){ + pass = false + break + } + } + else if(condition.operator === '>'){ + if(Number(varValue) > Number(condition.value)){ + pass = false + break + } + } + else if(condition.operator === '<'){ + if(Number(varValue) < Number(condition.value)){ + pass = false + break + } + } + else if(condition.operator === '>='){ + if(Number(varValue) >= Number(condition.value)){ + pass = false + break + } + } + else if(condition.operator === '<='){ + if(Number(varValue) <= Number(condition.value)){ + pass = false + break + } + } + } + } + else if(condition.type === 'exists'){ + let da = chat.message.slice(0-condition.depth).map((v)=>v.data).join(' ') + if(condition.type2 === 'strict'){ + pass = da.split(' ').includes(condition.value) + } + else if(condition.type2 === 'loose'){ + pass = da.toLowerCase().includes(condition.value.toLowerCase()) + } + else if(condition.type2 === 'regex'){ + pass = new RegExp(condition.value).test(da) + } + } + if(!pass){ + break + } + } + if(!pass){ + continue + } + for(const effect of trigger.effect){ + if(effect.type === 'setvar'){ + switch(effect.operator){ + case '=': + varValues[effect.var] = effect.value + break + case '+=': + varValues[effect.var] = (Number(varValues[effect.var]) + Number(effect.value)).toString() + break + case '-=': + varValues[effect.var] = (Number(varValues[effect.var]) - Number(effect.value)).toString() + break + case '*=': + varValues[effect.var] = (Number(varValues[effect.var]) * Number(effect.value)).toString() + break + case '/=': + varValues[effect.var] = (Number(varValues[effect.var]) / Number(effect.value)).toString() + break + } + varValuesChanged = true + } + else if(effect.type === 'systemprompt'){ + additonalSysPrompt[effect.location] += effect.value + "\n\n" + } + else if(effect.type === 'impersonate'){ + if(effect.role === 'user'){ + chat.message.push({role: 'user', data: effect.value}) + } + else if(effect.role === 'char'){ + chat.message.push({role: 'char', data: effect.value}) + } + } + } + } + + if(varValuesChanged){ + chat.message[chat.message.length-1].data = chat.message.at(-1).data.replaceAll(/{{(setvar|getvar)::.+?}}/gis,'') + Object.keys(varValues).map((v)=>`{{setvar::${v}::${varValues[v]}}}`).join('') + } + + char.chats[char.chatPage] = chat + + return {additonalSysPrompt, char} + } \ No newline at end of file