Fix various lua low level access bugs (#575)
### 1 Access key was not added properly
First commit fixes this
### 2 Lua engine was getting killed when it waits for async function
runLua function gets run in two different paths (i.e. runLua for lua
edit triggers and another one for onOuput handling) However, when one of
invocations waits for another promise from js side (i.e. low level
function) to finish, it gives chance for next trigger mode to run which
would call `if(luaEngine){ luaEngine.global.close() }` that will close
lua engine for the invocation that was waiting for promise which is
problematic.
Second commit fixes this by having a pool of engine for each trigger
mode having single mutex that prevents running same engine at the same
time while allowing different tigger modes to run parallely
### 3 Break statements were missing making every trigger to run for
input event.
This was causing insane lagging and buggy behaviours. Third commit fixes
this.
This commit is contained in:
88
src/ts/mutex.ts
Normal file
88
src/ts/mutex.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* A lock for synchronizing async operations.
|
||||
* Use this to protect a critical section
|
||||
* from getting modified by multiple async operations
|
||||
* at the same time.
|
||||
*/
|
||||
export class Mutex {
|
||||
/**
|
||||
* When multiple operations attempt to acquire the lock,
|
||||
* this queue remembers the order of operations.
|
||||
*/
|
||||
private _queue: {
|
||||
resolve: (release: ReleaseFunction) => void
|
||||
}[] = []
|
||||
|
||||
private _isLocked = false
|
||||
|
||||
/**
|
||||
* Wait until the lock is acquired.
|
||||
* @returns A function that releases the acquired lock.
|
||||
*/
|
||||
acquire() {
|
||||
return new Promise<ReleaseFunction>((resolve) => {
|
||||
this._queue.push({resolve})
|
||||
this._dispatch()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a function to be run serially.
|
||||
*
|
||||
* This ensures no other functions will start running
|
||||
* until `callback` finishes running.
|
||||
* @param callback Function to be run exclusively.
|
||||
* @returns The return value of `callback`.
|
||||
*/
|
||||
async runExclusive<T>(callback: () => Promise<T>) {
|
||||
const release = await this.acquire()
|
||||
try {
|
||||
return await callback()
|
||||
} finally {
|
||||
release()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the availability of the resource
|
||||
* and provide access to the next operation in the queue.
|
||||
*
|
||||
* _dispatch is called whenever availability changes,
|
||||
* such as after lock acquire request or lock release.
|
||||
*/
|
||||
private _dispatch() {
|
||||
if (this._isLocked) {
|
||||
// The resource is still locked.
|
||||
// Wait until next time.
|
||||
return
|
||||
}
|
||||
const nextEntry = this._queue.shift()
|
||||
if (!nextEntry) {
|
||||
// There is nothing in the queue.
|
||||
// Do nothing until next dispatch.
|
||||
return
|
||||
}
|
||||
// The resource is available.
|
||||
this._isLocked = true
|
||||
// and give access to the next operation
|
||||
// in the queue.
|
||||
nextEntry.resolve(this._buildRelease())
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a release function for each operation
|
||||
* so that it can release the lock after
|
||||
* the operation is complete.
|
||||
*/
|
||||
private _buildRelease(): ReleaseFunction {
|
||||
return () => {
|
||||
// Each release function make
|
||||
// the resource available again
|
||||
this._isLocked = false
|
||||
// and call dispatch.
|
||||
this._dispatch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ReleaseFunction = () => void
|
||||
@@ -11,14 +11,21 @@ import type { OpenAIChat } from ".";
|
||||
import { requestChatData } from "./request";
|
||||
import { v4 } from "uuid";
|
||||
import { getModuleTriggers } from "./modules";
|
||||
import { Mutex } from "../mutex";
|
||||
|
||||
let luaFactory:LuaFactory
|
||||
let luaEngine:LuaEngine
|
||||
let lastCode = ''
|
||||
let LuaSafeIds = new Set<string>()
|
||||
let LuaEditDisplayIds = new Set<string>()
|
||||
let LuaLowLevelIds = new Set<string>()
|
||||
|
||||
interface LuaEngineState {
|
||||
code: string;
|
||||
engine: LuaEngine;
|
||||
mutex: Mutex;
|
||||
}
|
||||
|
||||
let LuaEngines = new Map<string, LuaEngineState>()
|
||||
|
||||
export async function runLua(code:string, arg:{
|
||||
char?:character|groupChat|simpleCharacterArgument,
|
||||
chat?:Chat
|
||||
@@ -37,412 +44,431 @@ export async function runLua(code:string, arg:{
|
||||
let stopSending = false
|
||||
let lowLevelAccess = arg.lowLevelAccess ?? false
|
||||
|
||||
if(!luaEngine || lastCode !== code){
|
||||
if(luaEngine){
|
||||
luaEngine.global.close()
|
||||
if(!luaFactory){
|
||||
await makeLuaFactory()
|
||||
}
|
||||
let luaEngineState = LuaEngines.get(mode)
|
||||
let wasEmpty = false
|
||||
if (!luaEngineState) {
|
||||
luaEngineState = {
|
||||
code,
|
||||
engine: await luaFactory.createEngine({injectObjects: true}),
|
||||
mutex: new Mutex()
|
||||
}
|
||||
if(!luaFactory){
|
||||
makeLuaFactory()
|
||||
}
|
||||
luaEngine = await luaFactory.createEngine({injectObjects: true})
|
||||
luaEngine.global.set('setChatVar', (id:string,key:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id) && !LuaEditDisplayIds.has(id)){
|
||||
return
|
||||
}
|
||||
setVar(key, value)
|
||||
})
|
||||
luaEngine.global.set('getChatVar', (id:string,key:string) => {
|
||||
if(!LuaSafeIds.has(id) && !LuaEditDisplayIds.has(id)){
|
||||
return
|
||||
}
|
||||
return getVar(key)
|
||||
})
|
||||
luaEngine.global.set('stopChat', (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
stopSending = true
|
||||
})
|
||||
luaEngine.global.set('alertError', (id:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
alertError(value)
|
||||
})
|
||||
luaEngine.global.set('alertNormal', (id:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
alertNormal(value)
|
||||
})
|
||||
luaEngine.global.set('alertInput', (id:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
return alertInput(value)
|
||||
})
|
||||
luaEngine.global.set('setChat', (id:string, index:number, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const message = chat.message?.at(index)
|
||||
if(message){
|
||||
message.data = value
|
||||
}
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('setChatRole', (id:string, index:number, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const message = chat.message?.at(index)
|
||||
if(message){
|
||||
message.role = value === 'user' ? 'user' : 'char'
|
||||
}
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('cutChat', (id:string, start:number, end:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message = chat.message.slice(start,end)
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('removeChat', (id:string, index:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message.splice(index, 1)
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('addChat', (id:string, role:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
|
||||
chat.message.push({role: roleData, data: value})
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('insertChat', (id:string, index:number, role:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
|
||||
chat.message.splice(index, 0, {role: roleData, data: value})
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('removeChat', (id:string, index:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message.splice(index, 1)
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('getChatLength', (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
return chat.message.length
|
||||
})
|
||||
luaEngine.global.set('getFullChatMain', (id:string) => {
|
||||
const data = JSON.stringify(chat.message.map((v) => {
|
||||
return {
|
||||
role: v.role,
|
||||
data: v.data
|
||||
}
|
||||
}))
|
||||
return data
|
||||
})
|
||||
|
||||
luaEngine.global.set('setFullChatMain', (id:string, value:string) => {
|
||||
const realValue = JSON.parse(value)
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message = realValue.map((v) => {
|
||||
return {
|
||||
role: v.role,
|
||||
data: v.data
|
||||
LuaEngines.set(mode, luaEngineState)
|
||||
wasEmpty = true
|
||||
}
|
||||
return await luaEngineState.mutex.runExclusive(async () => {
|
||||
if (wasEmpty || code !== luaEngineState.code) {
|
||||
if (!wasEmpty)
|
||||
luaEngineState.engine.global.close()
|
||||
luaEngineState.engine = await luaFactory.createEngine({injectObjects: true})
|
||||
const luaEngine = luaEngineState.engine
|
||||
luaEngine.global.set('setChatVar', (id:string,key:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id) && !LuaEditDisplayIds.has(id)){
|
||||
return
|
||||
}
|
||||
setVar(key, value)
|
||||
})
|
||||
luaEngine.global.set('getChatVar', (id:string,key:string) => {
|
||||
if(!LuaSafeIds.has(id) && !LuaEditDisplayIds.has(id)){
|
||||
return
|
||||
}
|
||||
return getVar(key)
|
||||
})
|
||||
luaEngine.global.set('stopChat', (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
stopSending = true
|
||||
})
|
||||
luaEngine.global.set('alertError', (id:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
alertError(value)
|
||||
})
|
||||
luaEngine.global.set('alertNormal', (id:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
alertNormal(value)
|
||||
})
|
||||
luaEngine.global.set('alertInput', (id:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
return alertInput(value)
|
||||
})
|
||||
luaEngine.global.set('setChat', (id:string, index:number, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const message = chat.message?.at(index)
|
||||
if(message){
|
||||
message.data = value
|
||||
}
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('setChatRole', (id:string, index:number, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const message = chat.message?.at(index)
|
||||
if(message){
|
||||
message.role = value === 'user' ? 'user' : 'char'
|
||||
}
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('cutChat', (id:string, start:number, end:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message = chat.message.slice(start,end)
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('removeChat', (id:string, index:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message.splice(index, 1)
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('addChat', (id:string, role:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
|
||||
chat.message.push({role: roleData, data: value})
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('insertChat', (id:string, index:number, role:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
|
||||
chat.message.splice(index, 0, {role: roleData, data: value})
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('removeChat', (id:string, index:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message.splice(index, 1)
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
luaEngine.global.set('getChatLength', (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
return chat.message.length
|
||||
})
|
||||
luaEngine.global.set('getFullChatMain', (id:string) => {
|
||||
const data = JSON.stringify(chat.message.map((v) => {
|
||||
return {
|
||||
role: v.role,
|
||||
data: v.data
|
||||
}
|
||||
}))
|
||||
return data
|
||||
})
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
|
||||
luaEngine.global.set('logMain', (value:string) => {
|
||||
console.log(JSON.parse(value))
|
||||
})
|
||||
luaEngine.global.set('setFullChatMain', (id:string, value:string) => {
|
||||
const realValue = JSON.parse(value)
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat.message = realValue.map((v) => {
|
||||
return {
|
||||
role: v.role,
|
||||
data: v.data
|
||||
}
|
||||
})
|
||||
CurrentChat.set(chat)
|
||||
})
|
||||
|
||||
//Low Level Access
|
||||
luaEngine.global.set('similarity', async (id:string, source:string, value:string[]) => {
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
const processer = new HypaProcesser('MiniLM')
|
||||
await processer.addText(value)
|
||||
return await processer.similaritySearch(source)
|
||||
})
|
||||
luaEngine.global.set('logMain', (value:string) => {
|
||||
console.log(JSON.parse(value))
|
||||
})
|
||||
|
||||
luaEngine.global.set('generateImage', async (id:string, value:string, negValue:string = '') => {
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
const gen = await generateAIImage(value, char as character, negValue, 'inlay')
|
||||
if(!gen){
|
||||
return 'Error: Image generation failed'
|
||||
}
|
||||
const imgHTML = new Image()
|
||||
imgHTML.src = gen
|
||||
const inlay = await writeInlayImage(imgHTML)
|
||||
return `{{inlay::${inlay}}}`
|
||||
})
|
||||
//Low Level Access
|
||||
luaEngine.global.set('similarity', async (id:string, source:string, value:string[]) => {
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
const processer = new HypaProcesser('MiniLM')
|
||||
await processer.addText(value)
|
||||
return await processer.similaritySearch(source)
|
||||
})
|
||||
|
||||
luaEngine.global.set('LLMMain', async (id:string, promptStr:string) => {
|
||||
let prompt:{
|
||||
role: string,
|
||||
content: string
|
||||
}[] = JSON.parse(promptStr)
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
let promptbody:OpenAIChat[] = prompt.map((dict) => {
|
||||
let role:'system'|'user'|'assistant' = 'assistant'
|
||||
switch(dict['role']){
|
||||
case 'system':
|
||||
case 'sys':
|
||||
role = 'system'
|
||||
break
|
||||
case 'user':
|
||||
role = 'user'
|
||||
break
|
||||
case 'assistant':
|
||||
case 'bot':
|
||||
case 'char':{
|
||||
role = 'assistant'
|
||||
break
|
||||
luaEngine.global.set('generateImage', async (id:string, value:string, negValue:string = '') => {
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
const gen = await generateAIImage(value, char as character, negValue, 'inlay')
|
||||
if(!gen){
|
||||
return 'Error: Image generation failed'
|
||||
}
|
||||
const imgHTML = new Image()
|
||||
imgHTML.src = gen
|
||||
const inlay = await writeInlayImage(imgHTML)
|
||||
return `{{inlay::${inlay}}}`
|
||||
})
|
||||
|
||||
luaEngine.global.set('LLMMain', async (id:string, promptStr:string) => {
|
||||
let prompt:{
|
||||
role: string,
|
||||
content: string
|
||||
}[] = JSON.parse(promptStr)
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
let promptbody:OpenAIChat[] = prompt.map((dict) => {
|
||||
let role:'system'|'user'|'assistant' = 'assistant'
|
||||
switch(dict['role']){
|
||||
case 'system':
|
||||
case 'sys':
|
||||
role = 'system'
|
||||
break
|
||||
case 'user':
|
||||
role = 'user'
|
||||
break
|
||||
case 'assistant':
|
||||
case 'bot':
|
||||
case 'char':{
|
||||
role = 'assistant'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
content: dict['content'] ?? '',
|
||||
role: role,
|
||||
}
|
||||
})
|
||||
const result = await requestChatData({
|
||||
formated: promptbody,
|
||||
bias: {},
|
||||
useStreaming: false,
|
||||
noMultiGen: true,
|
||||
}, 'model')
|
||||
|
||||
if(result.type === 'fail'){
|
||||
return JSON.stringify({
|
||||
success: false,
|
||||
result: 'Error: ' + result.result
|
||||
})
|
||||
}
|
||||
|
||||
if(result.type === 'streaming' || result.type === 'multiline'){
|
||||
return JSON.stringify({
|
||||
success: false,
|
||||
result: result.result
|
||||
})
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
success: true,
|
||||
result: result.result
|
||||
})
|
||||
})
|
||||
|
||||
luaEngine.global.set('simpleLLM', async (id:string, prompt:string) => {
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
const result = await requestChatData({
|
||||
formated: [{
|
||||
role: 'user',
|
||||
content: prompt
|
||||
}],
|
||||
bias: {},
|
||||
useStreaming: false,
|
||||
noMultiGen: true,
|
||||
}, 'model')
|
||||
|
||||
if(result.type === 'fail'){
|
||||
return {
|
||||
success: false,
|
||||
result: 'Error: ' + result.result
|
||||
}
|
||||
}
|
||||
|
||||
if(result.type === 'streaming' || result.type === 'multiline'){
|
||||
return {
|
||||
success: false,
|
||||
result: result.result
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
content: dict['content'] ?? '',
|
||||
role: role,
|
||||
}
|
||||
})
|
||||
const result = await requestChatData({
|
||||
formated: promptbody,
|
||||
bias: {},
|
||||
useStreaming: false,
|
||||
noMultiGen: true,
|
||||
}, 'model')
|
||||
|
||||
if(result.type === 'fail'){
|
||||
return JSON.stringify({
|
||||
success: false,
|
||||
result: 'Error: ' + result.result
|
||||
})
|
||||
}
|
||||
|
||||
if(result.type === 'streaming' || result.type === 'multiline'){
|
||||
return JSON.stringify({
|
||||
success: false,
|
||||
result: result.result
|
||||
})
|
||||
}
|
||||
|
||||
return JSON.stringify({
|
||||
success: true,
|
||||
result: result.result
|
||||
})
|
||||
})
|
||||
|
||||
luaEngine.global.set('simpleLLM', async (id:string, prompt:string) => {
|
||||
if(!LuaLowLevelIds.has(id)){
|
||||
return
|
||||
}
|
||||
const result = await requestChatData({
|
||||
formated: [{
|
||||
role: 'user',
|
||||
content: prompt
|
||||
}],
|
||||
bias: {},
|
||||
useStreaming: false,
|
||||
noMultiGen: true,
|
||||
}, 'model')
|
||||
|
||||
if(result.type === 'fail'){
|
||||
return {
|
||||
success: false,
|
||||
result: 'Error: ' + result.result
|
||||
}
|
||||
}
|
||||
|
||||
if(result.type === 'streaming' || result.type === 'multiline'){
|
||||
return {
|
||||
success: false,
|
||||
success: true,
|
||||
result: result.result
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
luaEngine.global.set('getName', async (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.name
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
result: result.result
|
||||
}
|
||||
})
|
||||
|
||||
luaEngine.global.set('getName', async (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
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)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof name !== 'string'){
|
||||
throw('Invalid data type')
|
||||
}
|
||||
db.characters[selectedChar].name = name
|
||||
setDatabase(db)
|
||||
})
|
||||
|
||||
luaEngine.global.set('setName', async (id:string, name:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof name !== 'string'){
|
||||
throw('Invalid data type')
|
||||
}
|
||||
db.characters[selectedChar].name = name
|
||||
setDatabase(db)
|
||||
})
|
||||
luaEngine.global.set('setDescription', async (id:string, desc:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char =db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
throw('Invalid data type')
|
||||
}
|
||||
if(char.type === 'group'){
|
||||
throw('Character is a group')
|
||||
}
|
||||
char.desc = desc
|
||||
db.characters[selectedChar] = char
|
||||
setDatabase(db)
|
||||
})
|
||||
|
||||
luaEngine.global.set('setDescription', async (id:string, desc:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char =db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
throw('Invalid data type')
|
||||
}
|
||||
if(char.type === 'group'){
|
||||
throw('Character is a group')
|
||||
}
|
||||
char.desc = desc
|
||||
db.characters[selectedChar] = char
|
||||
setDatabase(db)
|
||||
})
|
||||
luaEngine.global.set('setCharacterFirstMessage', async (id:string, data:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
return false
|
||||
}
|
||||
char.firstMessage = data
|
||||
db.characters[selectedChar] = char
|
||||
setDatabase(db)
|
||||
return true
|
||||
})
|
||||
|
||||
luaEngine.global.set('setCharacterFirstMessage', async (id:string, data:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
return false
|
||||
}
|
||||
char.firstMessage = data
|
||||
db.characters[selectedChar] = char
|
||||
setDatabase(db)
|
||||
return true
|
||||
})
|
||||
luaEngine.global.set('getCharacterFirstMessage', async (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.firstMessage
|
||||
})
|
||||
|
||||
luaEngine.global.set('getCharacterFirstMessage', async (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.firstMessage
|
||||
})
|
||||
luaEngine.global.set('getBackgroundEmbedding', async (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.backgroundHTML
|
||||
})
|
||||
|
||||
luaEngine.global.set('getBackgroundEmbedding', async (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.backgroundHTML
|
||||
})
|
||||
luaEngine.global.set('setBackgroundEmbedding', async (id:string, data:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof data !== 'string'){
|
||||
return false
|
||||
}
|
||||
db.characters[selectedChar].backgroundHTML = data
|
||||
setDatabase(db)
|
||||
return true
|
||||
})
|
||||
|
||||
luaEngine.global.set('setBackgroundEmbedding', async (id:string, data:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof data !== 'string'){
|
||||
return false
|
||||
}
|
||||
db.characters[selectedChar].backgroundHTML = data
|
||||
setDatabase(db)
|
||||
return true
|
||||
})
|
||||
|
||||
await luaEngine.doString(luaCodeWarper(code))
|
||||
lastCode = code
|
||||
}
|
||||
let accessKey = v4()
|
||||
if(mode === 'editDisplay'){
|
||||
LuaEditDisplayIds.add(accessKey)
|
||||
}
|
||||
else{
|
||||
LuaSafeIds.add(accessKey)
|
||||
if(lowLevelAccess){
|
||||
LuaLowLevelIds.add(v4())
|
||||
await luaEngine.doString(luaCodeWarper(code))
|
||||
luaEngineState.code = code
|
||||
}
|
||||
}
|
||||
let res:any
|
||||
try {
|
||||
switch(mode){
|
||||
case 'input':{
|
||||
const func = luaEngine.global.get('onInput')
|
||||
if(func){
|
||||
res = await func(accessKey)
|
||||
}
|
||||
}
|
||||
case 'output':{
|
||||
const func = luaEngine.global.get('onOutput')
|
||||
if(func){
|
||||
res = await func(accessKey)
|
||||
}
|
||||
}
|
||||
case 'start':{
|
||||
const func = luaEngine.global.get('onStart')
|
||||
if(func){
|
||||
res = await func(accessKey)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
default:{
|
||||
const func = luaEngine.global.get(mode)
|
||||
if(func){
|
||||
res = await func(accessKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
if(res === false){
|
||||
stopSending = true
|
||||
let accessKey = v4()
|
||||
if(mode === 'editDisplay'){
|
||||
LuaEditDisplayIds.add(accessKey)
|
||||
}
|
||||
else{
|
||||
LuaSafeIds.add(accessKey)
|
||||
if(lowLevelAccess){
|
||||
LuaLowLevelIds.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)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'output':{
|
||||
const func = luaEngine.global.get('onOutput')
|
||||
if(func){
|
||||
res = await func(accessKey)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'start':{
|
||||
const func = luaEngine.global.get('onStart')
|
||||
if(func){
|
||||
res = await func(accessKey)
|
||||
}
|
||||
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)
|
||||
}
|
||||
break
|
||||
}
|
||||
default:{
|
||||
const func = luaEngine.global.get(mode)
|
||||
if(func){
|
||||
res = await func(accessKey)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
if(res === false){
|
||||
stopSending = true
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
||||
LuaSafeIds.delete(accessKey)
|
||||
LuaLowLevelIds.delete(accessKey)
|
||||
LuaSafeIds.delete(accessKey)
|
||||
LuaLowLevelIds.delete(accessKey)
|
||||
|
||||
return {
|
||||
stopSending, chat, res
|
||||
}
|
||||
return {
|
||||
stopSending, chat, res
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function makeLuaFactory(){
|
||||
|
||||
Reference in New Issue
Block a user