diff --git a/package.json b/package.json index 66885a23..cc15982a 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "png-chunk-text": "^1.0.0", "png-chunks-encode": "^1.0.0", "png-chunks-extract": "^1.0.0", + "pyodide": "^0.27.6", "rfdc": "^1.4.1", "rollup": "^3.29.4", "showdown": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d05f90f4..e49c8317 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -194,6 +194,9 @@ importers: png-chunks-extract: specifier: ^1.0.0 version: 1.0.0 + pyodide: + specifier: ^0.27.6 + version: 0.27.6 rfdc: specifier: ^1.4.1 version: 1.4.1 @@ -3112,6 +3115,10 @@ packages: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} + pyodide@0.27.6: + resolution: {integrity: sha512-ahiSHHs6iFKl2f8aO1wALINAlMNDLAtb44xCI87GQyH2tLDk8F8VWip3u1ZNIyglGSCYAOSFzWKwS1f9gBFVdg==} + engines: {node: '>=18.0.0'} + q@1.5.1: resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} engines: {node: '>=0.6.0', teleport: '>=0.2.0'} @@ -3832,6 +3839,18 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.18.2: + resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xcode@3.0.1: resolution: {integrity: sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA==} engines: {node: '>=10.0.0'} @@ -6702,6 +6721,13 @@ snapshots: punycode.js@2.3.1: {} + pyodide@0.27.6: + dependencies: + ws: 8.18.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + q@1.5.1: {} qs@6.11.0: @@ -7465,6 +7491,8 @@ snapshots: wrappy@1.0.2: {} + ws@8.18.2: {} + xcode@3.0.1: dependencies: simple-plist: 1.3.1 diff --git a/src/ts/observer.svelte.ts b/src/ts/observer.svelte.ts index 6e04d940..4e0c8d66 100644 --- a/src/ts/observer.svelte.ts +++ b/src/ts/observer.svelte.ts @@ -1,7 +1,7 @@ import { runTrigger } from "./process/triggers"; import { sleep } from "./util"; import { getCurrentCharacter, getCurrentChat, setCurrentChat } from "./storage/database.svelte"; -import { runLuaButtonTrigger } from "./process/lua"; +import { runLuaButtonTrigger } from "./process/scriptings"; import { globalFetch } from "./globalApi.svelte"; let bgmElement:HTMLAudioElement|null = null; diff --git a/src/ts/process/index.svelte.ts b/src/ts/process/index.svelte.ts index 1bdf7c0c..c855f0a2 100644 --- a/src/ts/process/index.svelte.ts +++ b/src/ts/process/index.svelte.ts @@ -26,7 +26,7 @@ import { addRerolls } from "./prereroll"; import { runImageEmbedding } from "./transformers"; import { hanuraiMemory } from "./memory/hanuraiMemory"; import { hypaMemoryV2 } from "./memory/hypav2"; -import { runLuaEditTrigger } from "./lua"; +import { runLuaEditTrigger } from "./scriptings"; import { getGlobalChatVar, parseChatML } from "../parser.svelte"; import { getModelInfo, LLMFlags } from "../model/modellist"; import { hypaMemoryV3 } from "./memory/hypav3"; diff --git a/src/ts/process/pyworker.ts b/src/ts/process/pyworker.ts new file mode 100644 index 00000000..71bfdd20 --- /dev/null +++ b/src/ts/process/pyworker.ts @@ -0,0 +1,105 @@ +//This is a web worker that runs Python code using Pyodide. + +import { loadPyodide, version as pyodideVersion, type PyodideInterface } from "pyodide"; + +type InitMessage = { + type: "init"; + id: string; + moduleFunctions: string[]; +} + +type FunctionResultMessage = { + type: "functionResult"; + callId: string; + result: any; +} + +type PythonMessage = { + type: 'python'; + code: string; +} + +type PyWorkerMessage = InitMessage | FunctionResultMessage | PythonMessage; + +let py: PyodideInterface; + +async function initPyodide() { + if(py){ + return py; + } + py = await loadPyodide({ + indexURL: `https://cdn.jsdelivr.net/pyodide/v${pyodideVersion}/full/` + }); + return py; +} + +self.onmessage = async (event:MessageEvent) => { + await initPyodide() + const { type } = event.data; + switch(type) { + case 'init':{ + const { id, moduleFunctions } = event.data as InitMessage; + let md: Record = {}; + for(const func of moduleFunctions) { + md[func] = (...args: any[]) => { + + return new Promise((resolve, reject) => { + const callid = crypto.randomUUID(); + self.postMessage({ + type: "call", + function: func, + args, + callId: callid + }); + + const callee = (e: CustomEvent) => { + if(e.detail.callId === callid) { + globalThis.removeEventListener("x-function-call", callee); + resolve(e.detail.result); + } + } + + globalThis.addEventListener("x-function-call", callee); + }) + } + } + py.registerJsModule('risuai', md) + self.postMessage({ + type: "init", + id, + version: pyodideVersion + }); + break + } + case 'functionResult': { + const { callId, result } = event.data as FunctionResultMessage; + globalThis.dispatchEvent(new CustomEvent("x-function-call", { + detail: { + callId, + result + } + })); + break; + } + case 'python': { + const { code } = event.data as PythonMessage; + try { + const result = await py.runPythonAsync(code); + self.postMessage({ + type: "pythonResult", + callId: crypto.randomUUID(), + result + }); + } catch (error) { + console.error("Error executing Python code:", error); + self.postMessage({ + type: "pythonResult", + callId: crypto.randomUUID(), + result: error + }); + } + break; + } + + } +}; \ No newline at end of file diff --git a/src/ts/process/lua.ts b/src/ts/process/scriptings.ts similarity index 71% rename from src/ts/process/lua.ts rename to src/ts/process/scriptings.ts index 6f8d94fb..a55ef459 100644 --- a/src/ts/process/lua.ts +++ b/src/ts/process/scriptings.ts @@ -16,36 +16,48 @@ import { tokenize } from "../tokenizer"; import { fetchNative } from "../globalApi.svelte"; import { loadLoreBookV3Prompt } from './lorebook.svelte'; import { getPersonaPrompt, getUserName } from '../util'; - let luaFactory:LuaFactory -let LuaSafeIds = new Set() -let LuaEditDisplayIds = new Set() -let LuaLowLevelIds = new Set() +let ScriptingSafeIds = new Set() +let ScriptingEditDisplayIds = new Set() +let ScriptingLowLevelIds = new Set() let lastRequestResetTime = 0 let lastRequestsCount = 0 -interface LuaEngineState { +interface BasicScriptingEngineState { code?: string; - engine?: LuaEngine; mutex: Mutex; chat?: Chat; setVar?: (key:string, value:string) => void, getVar?: (key:string) => string, } -let LuaEngines = new Map() -let luaFactoryPromise: Promise | null = null; -let pendingEngineCreations = new Map>(); +interface LuaScriptingEngineState extends BasicScriptingEngineState { + engine?: LuaEngine; + type: 'lua'; +} -export async function runLua(code:string, arg:{ +interface PythonScriptingEngineState extends BasicScriptingEngineState { + + type: 'py'; +} + +type ScriptingEngineState = LuaScriptingEngineState | PythonScriptingEngineState; + +let ScriptingEngines = new Map() +let luaFactoryPromise: Promise | null = null; +let pendingEngineCreations = new Map>(); + +export async function runScripted(code:string, arg:{ char?:character|groupChat|simpleCharacterArgument, chat?:Chat setVar?: (key:string, value:string) => void, getVar?: (key:string) => string, lowLevelAccess?: boolean, mode?: string, - data?: any + data?: any, + type?: 'lua'|'py' }){ + const type: 'lua'|'py' = arg.type ?? 'lua' const char = arg.char ?? getCurrentCharacter() const setVar = arg.setVar ?? setChatVar const getVar = arg.getVar ?? getChatVar @@ -55,63 +67,76 @@ export async function runLua(code:string, arg:{ let stopSending = false let lowLevelAccess = arg.lowLevelAccess ?? false - await ensureLuaFactory() - let luaEngineState = await getOrCreateEngineState(mode); + if(type === 'lua'){ + await ensureLuaFactory() + } + let ScriptingEngineState = await getOrCreateEngineState(mode, type); - return await luaEngineState.mutex.runExclusive(async () => { - luaEngineState.chat = chat - luaEngineState.setVar = setVar - luaEngineState.getVar = getVar - if (code !== luaEngineState.code) { - luaEngineState.engine?.global.close() - luaEngineState.code = code - luaEngineState.engine = await luaFactory.createEngine({injectObjects: true}) - const luaEngine = luaEngineState.engine - luaEngine.global.set('getChatVar', (id:string,key:string) => { - return luaEngineState.getVar(key) + return await ScriptingEngineState.mutex.runExclusive(async () => { + ScriptingEngineState.chat = chat + ScriptingEngineState.setVar = setVar + ScriptingEngineState.getVar = getVar + if (code !== ScriptingEngineState.code) { + let declareAPI:(name: string, func:Function) => void + + if(ScriptingEngineState.type === 'lua'){ + ScriptingEngineState.engine?.global.close() + ScriptingEngineState.code = code + ScriptingEngineState.engine = await luaFactory.createEngine({injectObjects: true}) + const luaEngine = ScriptingEngineState.engine + declareAPI = (name: string, func: Function) => { + luaEngine.global.set(name, func) + } + } + if(ScriptingEngineState.type === 'py'){ + + + } + declareAPI('getChatVar', (id:string,key:string) => { + return ScriptingEngineState.getVar(key) }) - luaEngine.global.set('setChatVar', (id:string,key:string, value:string) => { - if(!LuaSafeIds.has(id) && !LuaEditDisplayIds.has(id)){ + declareAPI('setChatVar', (id:string,key:string, value:string) => { + if(!ScriptingSafeIds.has(id) && !ScriptingEditDisplayIds.has(id)){ return } - luaEngineState.setVar(key, value) + ScriptingEngineState.setVar(key, value) }) - luaEngine.global.set('getGlobalVar', (id:string, key:string) => { + declareAPI('getGlobalVar', (id:string, key:string) => { return getGlobalChatVar(key) }) - luaEngine.global.set('stopChat', (id:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('stopChat', (id:string) => { + if(!ScriptingSafeIds.has(id)){ return } stopSending = true }) - luaEngine.global.set('alertError', (id:string, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('alertError', (id:string, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } alertError(value) }) - luaEngine.global.set('alertNormal', (id:string, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('alertNormal', (id:string, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } alertNormal(value) }) - luaEngine.global.set('alertInput', (id:string, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('alertInput', (id:string, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } return alertInput(value) }) - luaEngine.global.set('alertSelect', (id:string, value:string[]) => { - if(!LuaSafeIds.has(id)){ + declareAPI('alertSelect', (id:string, value:string[]) => { + if(!ScriptingSafeIds.has(id)){ return } return alertSelect(value) }) - luaEngine.global.set('getChatMain', (id:string, index:number) => { - const chat = luaEngineState.chat.message.at(index) + declareAPI('getChatMain', (id:string, index:number) => { + const chat = ScriptingEngineState.chat.message.at(index) if(!chat){ return JSON.stringify(null) } @@ -123,64 +148,64 @@ export async function runLua(code:string, arg:{ return JSON.stringify(data) }) - luaEngine.global.set('setChat', (id:string, index:number, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('setChat', (id:string, index:number, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } - const message = luaEngineState.chat.message?.at(index) + const message = ScriptingEngineState.chat.message?.at(index) if(message){ message.data = value } }) - luaEngine.global.set('setChatRole', (id:string, index:number, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('setChatRole', (id:string, index:number, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } - const message = luaEngineState.chat.message?.at(index) + const message = ScriptingEngineState.chat.message?.at(index) if(message){ message.role = value === 'user' ? 'user' : 'char' } }) - luaEngine.global.set('cutChat', (id:string, start:number, end:number) => { - if(!LuaSafeIds.has(id)){ + declareAPI('cutChat', (id:string, start:number, end:number) => { + if(!ScriptingSafeIds.has(id)){ return } - luaEngineState.chat.message = luaEngineState.chat.message.slice(start,end) + ScriptingEngineState.chat.message = ScriptingEngineState.chat.message.slice(start,end) }) - luaEngine.global.set('removeChat', (id:string, index:number) => { - if(!LuaSafeIds.has(id)){ + declareAPI('removeChat', (id:string, index:number) => { + if(!ScriptingSafeIds.has(id)){ return } - luaEngineState.chat.message.splice(index, 1) + ScriptingEngineState.chat.message.splice(index, 1) }) - luaEngine.global.set('addChat', (id:string, role:string, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('addChat', (id:string, role:string, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } let roleData:'user'|'char' = role === 'user' ? 'user' : 'char' - luaEngineState.chat.message.push({role: roleData, data: value}) + ScriptingEngineState.chat.message.push({role: roleData, data: value}) }) - luaEngine.global.set('insertChat', (id:string, index:number, role:string, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('insertChat', (id:string, index:number, role:string, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } let roleData:'user'|'char' = role === 'user' ? 'user' : 'char' - luaEngineState.chat.message.splice(index, 0, {role: roleData, data: value}) + ScriptingEngineState.chat.message.splice(index, 0, {role: roleData, data: value}) }) - luaEngine.global.set('getTokens', async (id:string, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('getTokens', async (id:string, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } return await tokenize(value) }) - luaEngine.global.set('getChatLength', (id:string) => { - return luaEngineState.chat.message.length + declareAPI('getChatLength', (id:string) => { + return ScriptingEngineState.chat.message.length }) - luaEngine.global.set('getFullChatMain', (id:string) => { - const data = JSON.stringify(luaEngineState.chat.message.map((v) => { + declareAPI('getFullChatMain', (id:string) => { + const data = JSON.stringify(ScriptingEngineState.chat.message.map((v) => { return { role: v.role, data: v.data, @@ -190,13 +215,13 @@ export async function runLua(code:string, arg:{ return data }) - luaEngine.global.set('setFullChatMain', (id:string, value:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('setFullChatMain', (id:string, value:string) => { + if(!ScriptingSafeIds.has(id)){ return } const realValue = JSON.parse(value) - luaEngineState.chat.message = realValue.map((v) => { + ScriptingEngineState.chat.message = realValue.map((v) => { return { role: v.role, data: v.data @@ -204,20 +229,20 @@ export async function runLua(code:string, arg:{ }) }) - luaEngine.global.set('logMain', (value:string) => { + declareAPI('logMain', (value:string) => { console.log(JSON.parse(value)) }) - luaEngine.global.set('reloadDisplay', (id:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('reloadDisplay', (id:string) => { + if(!ScriptingSafeIds.has(id)){ return } ReloadGUIPointer.set(get(ReloadGUIPointer) + 1) }) //Low Level Access - luaEngine.global.set('similarity', async (id:string, source:string, value:string[]) => { - if(!LuaLowLevelIds.has(id)){ + declareAPI('similarity', async (id:string, source:string, value:string[]) => { + if(!ScriptingLowLevelIds.has(id)){ return } const processer = new HypaProcesser() @@ -225,8 +250,8 @@ export async function runLua(code:string, arg:{ return await processer.similaritySearch(source) }) - luaEngine.global.set('request', async (id:string, url:string) => { - if(!LuaLowLevelIds.has(id)){ + declareAPI('request', async (id:string, url:string) => { + if(!ScriptingLowLevelIds.has(id)){ return } @@ -294,8 +319,8 @@ export async function runLua(code:string, arg:{ } }) - luaEngine.global.set('generateImage', async (id:string, value:string, negValue:string = '') => { - if(!LuaLowLevelIds.has(id)){ + declareAPI('generateImage', async (id:string, value:string, negValue:string = '') => { + if(!ScriptingLowLevelIds.has(id)){ return } const gen = await generateAIImage(value, char as character, negValue, 'inlay') @@ -308,16 +333,16 @@ export async function runLua(code:string, arg:{ return `{{inlay::${inlay}}}` }) - luaEngine.global.set('hash', async (id:string, value:string) => { + declareAPI('hash', async (id:string, value:string) => { return await hasher(new TextEncoder().encode(value)) }) - luaEngine.global.set('LLMMain', async (id:string, promptStr:string) => { + declareAPI('LLMMain', async (id:string, promptStr:string) => { let prompt:{ role: string, content: string }[] = JSON.parse(promptStr) - if(!LuaLowLevelIds.has(id)){ + if(!ScriptingLowLevelIds.has(id)){ return } let promptbody:OpenAIChat[] = prompt.map((dict) => { @@ -370,8 +395,8 @@ export async function runLua(code:string, arg:{ }) }) - luaEngine.global.set('simpleLLM', async (id:string, prompt:string) => { - if(!LuaLowLevelIds.has(id)){ + declareAPI('simpleLLM', async (id:string, prompt:string) => { + if(!ScriptingLowLevelIds.has(id)){ return } const result = await requestChatData({ @@ -404,15 +429,15 @@ export async function runLua(code:string, arg:{ } }) - luaEngine.global.set('getName', async (id:string) => { + declareAPI('getName', async (id:string) => { const db = getDatabase() const selectedChar = get(selectedCharID) const char = db.characters[selectedChar] return char.name }) - luaEngine.global.set('setName', async (id:string, name:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('setName', async (id:string, name:string) => { + if(!ScriptingSafeIds.has(id)){ return } const db = getDatabase() @@ -424,8 +449,8 @@ export async function runLua(code:string, arg:{ setDatabase(db) }) - luaEngine.global.set('getDescription', async (id:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('getDescription', async (id:string) => { + if(!ScriptingSafeIds.has(id)){ return } const db = getDatabase() @@ -437,8 +462,8 @@ export async function runLua(code:string, arg:{ return char.desc }) - luaEngine.global.set('setDescription', async (id:string, desc:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('setDescription', async (id:string, desc:string) => { + if(!ScriptingSafeIds.has(id)){ return } const db = getDatabase() @@ -455,15 +480,15 @@ export async function runLua(code:string, arg:{ setDatabase(db) }) - luaEngine.global.set('getCharacterFirstMessage', async (id:string) => { + declareAPI('getCharacterFirstMessage', async (id:string) => { const db = getDatabase() const selectedChar = get(selectedCharID) const char = db.characters[selectedChar] return char.firstMessage }) - luaEngine.global.set('setCharacterFirstMessage', async (id:string, data:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('setCharacterFirstMessage', async (id:string, data:string) => { + if(!ScriptingSafeIds.has(id)){ return } const db = getDatabase() @@ -478,11 +503,11 @@ export async function runLua(code:string, arg:{ return true }) - luaEngine.global.set('getPersonaName', (id:string) => { + declareAPI('getPersonaName', (id:string) => { return getUserName() }) - luaEngine.global.set('getPersonaDescription', (id:string) => { + declareAPI('getPersonaDescription', (id:string) => { const db = getDatabase() const selectedChar = get(selectedCharID) const char = db.characters[selectedChar] @@ -490,12 +515,12 @@ export async function runLua(code:string, arg:{ return risuChatParser(getPersonaPrompt(), { chara: char }) }) - luaEngine.global.set('getAuthorsNote', (id:string) => { - return luaEngineState.chat?.note ?? '' + declareAPI('getAuthorsNote', (id:string) => { + return ScriptingEngineState.chat?.note ?? '' }) - luaEngine.global.set('getBackgroundEmbedding', async (id:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('getBackgroundEmbedding', async (id:string) => { + if(!ScriptingSafeIds.has(id)){ return } const db = getDatabase() @@ -504,8 +529,8 @@ export async function runLua(code:string, arg:{ return char.backgroundHTML }) - luaEngine.global.set('setBackgroundEmbedding', async (id:string, data:string) => { - if(!LuaSafeIds.has(id)){ + declareAPI('setBackgroundEmbedding', async (id:string, data:string) => { + if(!ScriptingSafeIds.has(id)){ return } const db = getDatabase() @@ -519,7 +544,7 @@ export async function runLua(code:string, arg:{ }) // Lore books - luaEngine.global.set('getLoreBooksMain', (id:string, search: string) => { + declareAPI('getLoreBooksMain', (id:string, search: string) => { const db = getDatabase() const selectedChar = db.characters[get(selectedCharID)] if (selectedChar.type !== 'character') { @@ -532,8 +557,8 @@ export async function runLua(code:string, arg:{ return JSON.stringify(found.map((b) => ({ ...b, content: risuChatParser(b.content, { chara: selectedChar }) }))) }) - luaEngine.global.set('loadLoreBooksMain', async (id:string, reserve:number) => { - if(!LuaLowLevelIds.has(id)){ + declareAPI('loadLoreBooksMain', async (id:string, reserve:number) => { + if(!ScriptingLowLevelIds.has(id)){ return } @@ -575,12 +600,12 @@ export async function runLua(code:string, arg:{ return JSON.stringify(loreBooks) }) - luaEngine.global.set('axLLMMain', async (id:string, promptStr:string) => { + declareAPI('axLLMMain', async (id:string, promptStr:string) => { let prompt:{ role: string, content: string }[] = JSON.parse(promptStr) - if(!LuaLowLevelIds.has(id)){ + if(!ScriptingLowLevelIds.has(id)){ return } let promptbody:OpenAIChat[] = prompt.map((dict) => { @@ -633,80 +658,83 @@ export async function runLua(code:string, arg:{ }) }) - await luaEngine.doString(luaCodeWarper(code)) - luaEngineState.code = code + if(ScriptingEngineState.type === 'lua'){ + await ScriptingEngineState.engine?.doString(luaCodeWarper(code)) + } + ScriptingEngineState.code = code } let accessKey = v4() if(mode === 'editDisplay'){ - LuaEditDisplayIds.add(accessKey) + ScriptingEditDisplayIds.add(accessKey) } else{ - LuaSafeIds.add(accessKey) + ScriptingSafeIds.add(accessKey) if(lowLevelAccess){ - LuaLowLevelIds.add(accessKey) + ScriptingLowLevelIds.add(accessKey) } } let res:any - const luaEngine = luaEngineState.engine - try { - switch(mode){ - case 'input':{ - const func = luaEngine.global.get('onInput') - if(func){ - res = await func(accessKey) + if(ScriptingEngineState.type === 'lua'){ + const luaEngine = ScriptingEngineState.engine + try { + switch(mode){ + case 'input':{ + const func = luaEngine.global.get('onInput') + if(func){ + res = await func(accessKey) + } + break } - break - } - case 'output':{ - const func = luaEngine.global.get('onOutput') - if(func){ - res = await func(accessKey) + case 'output':{ + const func = luaEngine.global.get('onOutput') + if(func){ + res = await func(accessKey) + } + break } - break - } - case 'start':{ - const func = luaEngine.global.get('onStart') - if(func){ - res = await func(accessKey) + case 'start':{ + const func = luaEngine.global.get('onStart') + if(func){ + res = await func(accessKey) + } + break } - break - } - case 'onButtonClick':{ - const func = luaEngine.global.get('onButtonClick') - if(func){ - res = await func(accessKey, data) + case 'onButtonClick':{ + const func = luaEngine.global.get('onButtonClick') + if(func){ + res = await func(accessKey, data) + } + break } - break - } - case 'editRequest': - case 'editDisplay': - case 'editInput': - case 'editOutput':{ - const func = luaEngine.global.get('callListenMain') - if(func){ - res = await func(mode, accessKey, JSON.stringify(data)) - res = JSON.parse(res) + case 'editRequest': + case 'editDisplay': + case 'editInput': + case 'editOutput':{ + const func = luaEngine.global.get('callListenMain') + if(func){ + res = await func(mode, accessKey, JSON.stringify(data)) + res = JSON.parse(res) + } + break } - break - } - default:{ - const func = luaEngine.global.get(mode) - if(func){ - res = await func(accessKey) + default:{ + const func = luaEngine.global.get(mode) + if(func){ + res = await func(accessKey) + } + break } - break + } + if(res === false){ + stopSending = true } - } - if(res === false){ - stopSending = true + } catch (error) { + console.error(error) } - } catch (error) { - console.error(error) } - - LuaSafeIds.delete(accessKey) - LuaLowLevelIds.delete(accessKey) - chat = luaEngineState.chat + ScriptingSafeIds.delete(accessKey) + ScriptingLowLevelIds.delete(accessKey) + chat = ScriptingEngineState.chat return { stopSending, chat, res @@ -756,8 +784,9 @@ async function ensureLuaFactory() { async function getOrCreateEngineState( mode: string, -): Promise { - let engineState = LuaEngines.get(mode); + type: 'lua'|'py' +): Promise { + let engineState = ScriptingEngines.get(mode); if (engineState) { return engineState; } @@ -768,10 +797,11 @@ async function getOrCreateEngineState( } const creationPromise = (async () => { - const engineState: LuaEngineState = { + const engineState: ScriptingEngineState = { mutex: new Mutex(), + type: type, }; - LuaEngines.set(mode, engineState); + ScriptingEngines.set(mode, engineState); pendingEngineCreations.delete(mode); @@ -948,7 +978,7 @@ export async function runLuaEditTrigger(char:character|groupChat| for(let trigger of triggers){ if(trigger?.effect?.[0]?.type === 'triggerlua'){ - const runResult = await runLua(trigger.effect[0].code, { + const runResult = await runScripted(trigger.effect[0].code, { char: char, lowLevelAccess: false, mode: mode, @@ -975,7 +1005,7 @@ export async function runLuaButtonTrigger(char:character|groupChat|simpleCharact for(let trigger of triggers){ if(trigger?.effect?.[0]?.type === 'triggerlua'){ - runResult = await runLua(trigger.effect[0].code, { + runResult = await runScripted(trigger.effect[0].code, { char: char, lowLevelAccess: trigger.lowLevelAccess, mode: 'onButtonClick', diff --git a/src/ts/process/scripts.ts b/src/ts/process/scripts.ts index ed4c9ed7..582a04d7 100644 --- a/src/ts/process/scripts.ts +++ b/src/ts/process/scripts.ts @@ -8,7 +8,7 @@ import { selectSingleFile } from "../util"; import { assetRegex, type CbsConditions, risuChatParser as risuChatParserOrg, type simpleCharacterArgument } from "../parser.svelte"; import { getModuleAssets, getModuleRegexScripts, getModuleTriggers } from "./modules"; import { HypaProcesser } from "./memory/hypamemory"; -import { runLuaEditTrigger } from "./lua"; +import { runLuaEditTrigger } from "./scriptings"; import { pluginV2 } from "../plugins/plugins"; import { runTrigger } from "./triggers"; diff --git a/src/ts/process/triggers.ts b/src/ts/process/triggers.ts index 07d9bcf2..525ed135 100644 --- a/src/ts/process/triggers.ts +++ b/src/ts/process/triggers.ts @@ -12,7 +12,7 @@ import { HypaProcesser } from "./memory/hypamemory"; import { requestChatData, type OpenAIChatExtra } from "./request"; import { generateAIImage } from "./stableDiff"; import { writeInlayImage } from "./files/inlays"; -import { runLua } from "./lua"; +import { runScripted } from "./scriptings"; export interface triggerscript{ @@ -1148,7 +1148,7 @@ export async function runTrigger(char:character,mode:triggerMode, arg:{ } case 'triggerlua':{ - const triggerCodeResult = await runLua(effect.code,{ + const triggerCodeResult = await runScripted(effect.code,{ lowLevelAccess: trigger.lowLevelAccess, mode: mode === 'manual' ? arg.manualName : mode, setVar: setVar,