fix: lua chat functions (#782)

# PR Checklist
- [ ] Have you checked if it works normally in all models? *Ignore this
if it doesn't use models.*
- [ ] Have you checked if it works normally in all web, local, and node
hosted versions? If it doesn't, have you blocked it in those versions?
- [ ] Have you added type definitions?

# Description
The community have reported an issue where chat array-related effects
malfunction when using modules using Lua alongside modules using blocks.
It appears that my previous PR, #639, may be the cause of this problem.
This PR included the following changes:

1. Reverted a previous change to allow Lua triggers to cycle correctly
within the trigger pipeline.
2. After that, the issue that the previous PR attempted to fix has
(understandably) resurfaced. To address this, I've taken a different
approach: To prevent a situation where a created Lua mutex would
eternally reference a single chat object if not initialized again, I've
added a chat variable to the `luaEngineState` interface and updated it
on every call.
3. I noticed that the `removeChat` function was included twice in the
Lua bindings. I've removed one. (Or was this intentional?)
4. Modified the `getFullChat` function to also return the creation time
of the chat.

Just in case, I've also attached a link to the bot card with Lua trigger
I used for testing: https://files.catbox.moe/ujqt3o.jpeg
This commit is contained in:
kwaroran
2025-03-13 16:37:32 +09:00
committed by GitHub
3 changed files with 24 additions and 37 deletions

View File

@@ -44,7 +44,12 @@ function nodeObserve(node:HTMLElement){
if(currentChar.type === 'group'){
return;
}
await runLuaButtonTrigger(currentChar, btnEvent);
const triggerResult = await runLuaButtonTrigger(currentChar, btnEvent);
if(triggerResult){
setCurrentChat(triggerResult.chat);
}
}, {
passive: true,
});

View File

@@ -22,6 +22,7 @@ interface LuaEngineState {
code: string;
engine: LuaEngine;
mutex: Mutex;
chat: Chat;
}
let LuaEngines = new Map<string, LuaEngineState>()
@@ -53,10 +54,13 @@ export async function runLua(code:string, arg:{
luaEngineState = {
code,
engine: await luaFactory.createEngine({injectObjects: true}),
mutex: new Mutex()
mutex: new Mutex(),
chat
}
LuaEngines.set(mode, luaEngineState)
wasEmpty = true
} else {
luaEngineState.chat = chat
}
return await luaEngineState.mutex.runExclusive(async () => {
if (wasEmpty || code !== luaEngineState.code) {
@@ -104,79 +108,58 @@ export async function runLua(code:string, arg:{
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
const message = chat.message?.at(index)
const message = luaEngineState.chat.message?.at(index)
if(message){
message.data = value
}
setCurrentChat(chat)
})
luaEngine.global.set('setChatRole', (id:string, index:number, value:string) => {
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
const message = chat.message?.at(index)
const message = luaEngineState.chat.message?.at(index)
if(message){
message.role = value === 'user' ? 'user' : 'char'
}
setCurrentChat(chat)
})
luaEngine.global.set('cutChat', (id:string, start:number, end:number) => {
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
chat.message = chat.message.slice(start,end)
setCurrentChat(chat)
luaEngineState.chat.message = luaEngineState.chat.message.slice(start,end)
})
luaEngine.global.set('removeChat', (id:string, index:number) => {
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
chat.message.splice(index, 1)
setCurrentChat(chat)
luaEngineState.chat.message.splice(index, 1)
})
luaEngine.global.set('addChat', (id:string, role:string, value:string) => {
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
chat.message.push({role: roleData, data: value})
setCurrentChat(chat)
luaEngineState.chat.message.push({role: roleData, data: value})
})
luaEngine.global.set('insertChat', (id:string, index:number, role:string, value:string) => {
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
chat.message.splice(index, 0, {role: roleData, data: value})
setCurrentChat(chat)
})
luaEngine.global.set('removeChat', (id:string, index:number) => {
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
chat.message.splice(index, 1)
setCurrentChat(chat)
luaEngineState.chat.message.splice(index, 0, {role: roleData, data: value})
})
luaEngine.global.set('getChatLength', (id:string) => {
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
return chat.message.length
return luaEngineState.chat.message.length
})
luaEngine.global.set('getFullChatMain', (id:string) => {
chat = getCurrentChat()
const data = JSON.stringify(chat.message.map((v) => {
const data = JSON.stringify(luaEngineState.chat.message.map((v) => {
return {
role: v.role,
data: v.data
data: v.data,
time: v.time ?? 0
}
}))
return data
@@ -187,14 +170,12 @@ export async function runLua(code:string, arg:{
if(!LuaSafeIds.has(id)){
return
}
chat = getCurrentChat()
chat.message = realValue.map((v) => {
luaEngineState.chat.message = realValue.map((v) => {
return {
role: v.role,
data: v.data
}
})
setCurrentChat(chat)
})
luaEngine.global.set('logMain', (value:string) => {
@@ -550,6 +531,7 @@ export async function runLua(code:string, arg:{
LuaSafeIds.delete(accessKey)
LuaLowLevelIds.delete(accessKey)
chat = luaEngineState.chat
return {
stopSending, chat, res

View File

@@ -1151,7 +1151,7 @@ export async function runTrigger(char:character,mode:triggerMode, arg:{
if(triggerCodeResult.stopSending){
stopSending = true
}
chat = getCurrentChat()
chat = triggerCodeResult.chat
break
}