This commit is contained in:
kwaroran
2025-04-13 00:34:01 +09:00
19 changed files with 347 additions and 206 deletions

3
.gitignore vendored
View File

@@ -42,4 +42,5 @@ __pycache__/
.tauri/
dist.zip
/scripts/
.env
.env
/server/node/ssl/certificate

View File

@@ -9,6 +9,8 @@ app.use(express.static(path.join(process.cwd(), 'dist'), {index: false}));
app.use(express.json({ limit: '50mb' }));
app.use(express.raw({ type: 'application/octet-stream', limit: '50mb' }));
const {pipeline} = require('stream/promises')
const https = require('https');
const sslPath = path.join(process.cwd(), 'server/node/ssl/certificate');
let password = ''
@@ -294,6 +296,57 @@ app.post('/api/write', async (req, res, next) => {
}
});
app.listen(6001, () => {
console.log("Server is listening on http://localhost:6001/");
});
async function getHttpsOptions() {
const keyPath = path.join(sslPath, 'server.key');
const certPath = path.join(sslPath, 'server.crt');
console.log(keyPath)
console.log(certPath)
try {
await fs.access(keyPath);
await fs.access(certPath);
const [key, cert] = await Promise.all([
fs.readFile(keyPath),
fs.readFile(certPath)
]);
return { key, cert };
} catch (error) {
console.error('SSL setup errors:', error.message);
console.log('Start the server with HTTP instead of HTTPS...');
return null;
}
}
async function startServer() {
const port = process.env.PORT || 6001;
const httpsOptions = await getHttpsOptions();
if (httpsOptions) {
// HTTPS
https.createServer(httpsOptions, app).listen(port, () => {
console.log("HTTPS server is running.");
console.log("https://localhost:6001/");
});
} else {
// HTTP
app.listen(port, () => {
console.log("HTTP server is running.");
console.log("http://localhost:6001/");
});
}
}
(async () => {
try {
await startServer();
} catch (error) {
console.error('Fail to start server :', error);
}
})();

View File

@@ -0,0 +1,5 @@
@echo off
mkdir certificate 2>nul
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout certificate\ca.key -out certificate\ca.crt -config ca.conf
openssl req -new -nodes -newkey rsa:2048 -keyout certificate\server.key -out certificate\server.csr -config server.conf
openssl x509 -req -in certificate\server.csr -CA certificate\ca.crt -CAkey certificate\ca.key -CAcreateserial -out certificate\server.crt -days 3650 -extensions req_ext -extfile server.conf

View File

@@ -0,0 +1,8 @@
#!/bin/bash
mkdir -p certificate
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout certificate/ca.key -out certificate/ca.crt -config ca.conf
openssl req -new -nodes -newkey rsa:2048 -keyout certificate/server.key -out certificate/server.csr -config server.conf
openssl x509 -req -in certificate/server.csr -CA certificate/ca.crt -CAkey certificate/ca.key -CAcreateserial -out certificate/server.crt -days 3650 -extensions req_ext -extfile server.conf
chmod 644 certificate/ca.key certificate/server.key
chmod 644 certificate/ca.crt certificate/server.crt certificate/server.csr

19
server/node/ssl/ca.conf Normal file
View File

@@ -0,0 +1,19 @@
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
x509_extensions = ca_ext
[ dn ]
C = KR
ST = Kivotos
L = Millennium Science School
O = Game Development Department
OU = Certificate Authority
CN = Aris CA
[ ca_ext ]
basicConstraints = critical,CA:TRUE
keyUsage = critical,keyCertSign,cRLSign
subjectKeyIdentifier = hash

View File

@@ -0,0 +1,23 @@
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ dn ]
C = KR
ST = Kivotos
L = Millennium Science School
O = Game Development Department
OU = Tendou Aris
CN = localhost
[ req_ext ]
subjectAltName = @alt_names
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
[ alt_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1

View File

@@ -1,5 +1,5 @@
export const languageChinese = {
"formating": {
"formating": {
"main": "主提示词",
"jailbreak": "越狱提示词",
"chats": "历史聊天",
@@ -379,7 +379,8 @@ export const languageChinese = {
"globalLoreBook": "全局世界书",
"globalRegexScript": "全局正则表达式",
"accessibility": "辅助功能",
"sendWithEnter": "使用 Enter 键发送",
"sendWithEnter": "使用 Enter 键发送取消检查时Shift + Enter更改为消息传送。",
"fixedChatTextarea": "固定聊天窗口底部",
"clickToEdit": "点击文字进行编辑",
"setNodePassword": "设置密码以提升安全性",
"inputNodePassword": "输入密码。如果忘记密码,请删除服务器文档中的 save/__password.txt 并重启服务器。",

View File

@@ -48,33 +48,33 @@ export const languageGerman = {
loreorder: "Wenn die Insert-Reihenfolge höher ist, wirkt sie sich stärker auf das Modell aus und wird weniger stark beeinträchtigt, wenn viele Lore aktiviert sind",
bias: "Bias ist ein Schlüssel-Wert Attribut, das die Wahrscheinlichkeit des Vorkommens bestimmter Ausdrücke ändert.\nDas Attribut kann Werte zwischen -100 und 100 annehmen. Ausdrücke mit höheren Werten werden häufiger auftreten, während solche mit niedrigeren Werten seltener auftreten werden.\nAchtung: Stellen Sie sicher, dass der korrekte Tokenizer eingestellt ist, andernfalls kann diese Funktion nicht ordnungsgemäß umgesetzt werden.",
emotion: "Die Option 'Emotion Images' zeigt ein Bild abhängig von der aktuellen Emotion des Charakters, die anhand seiner/ihrer Antwort analysiert wird. Sie müssen den Emotionsnamen als Wort eingeben (wie z.B. Freude, Glück, Angst usw). Die Emotion mit dem Namen **neutral** wird als Standardemotion verwendet, sofern sie vorhanden ist. Es müssen mindestens 3 Bilder vorhanden sein, damit die Emotionszuweisung ordnungsgemäß funktioniert.",
imggen: "Die Option 'Image Generation' generiert und zeigt ein Bild aus einem externen Programm an. Das Bild wird anhand des aktuellen Chats generiert, der durch die Bild-Anweisung analysiert wird.\n\nDie Bildgenerierung basiert auf konfigurierbaren Schlüsselwertargumenten, darunter:"
+ "\n\n Der Schlüssel **'always'** gilt immer und ändert sich nicht. Der Schlüssel '**negative**' gilt immer negativ für die Bildgenerierung"
+ "\n\nObjekte mit dem Wert eines anderen Schlüssels ändern sich entsprechend dem Namen des Schlüssels, während der Chat fortschreitet"
+ "\n\nWenn ein Schlüssel ein Sonderzeichen am Anfang seines Namens enthält, bekommt dieser eine besondere Wirkung"
+ "\n- Wenn der Schlüssel mit **|** beginnt, ändert sich der Wert des Schlüssels nicht"
+ "\n- Wenn der Schlüssel mit **$** beginnt, ändert sich der Wert des Schlüssels höchstwahrscheinlich"
+ "\n\nWenn das Bild zum ersten Mal generiert wird, können Sie es nur ändern, indem Sie 'Aktuelle Bilddatengenerierung' unten modifizieren",
imggen: "Die Option 'Image Generation' generiert und zeigt ein Bild aus einem externen Programm an. Das Bild wird anhand des aktuellen Chats generiert, der durch die Bild-Anweisung analysiert wird.\n\nDie Bildgenerierung basiert auf konfigurierbaren Schlüsselwertargumenten, darunter:"
+ "\n\n Der Schlüssel **'always'** gilt immer und ändert sich nicht. Der Schlüssel '**negative**' gilt immer negativ für die Bildgenerierung"
+ "\n\nObjekte mit dem Wert eines anderen Schlüssels ändern sich entsprechend dem Namen des Schlüssels, während der Chat fortschreitet"
+ "\n\nWenn ein Schlüssel ein Sonderzeichen am Anfang seines Namens enthält, bekommt dieser eine besondere Wirkung"
+ "\n- Wenn der Schlüssel mit **|** beginnt, ändert sich der Wert des Schlüssels nicht"
+ "\n- Wenn der Schlüssel mit **$** beginnt, ändert sich der Wert des Schlüssels höchstwahrscheinlich"
+ "\n\nWenn das Bild zum ersten Mal generiert wird, können Sie es nur ändern, indem Sie 'Aktuelle Bilddatengenerierung' unten modifizieren",
regexScript: "RegEx-Skript ist ein benutzerdefiniertes Skript, das Zeichenfolgen,\n\ndie IN entsprechen, durch OUT ersetzt. Es gibt vier Optionstypen:"
+ "\n\n- **Eingabe ändern** ändert die Eingabe des Benutzers"
+ "\n\n- **Ausgabe ändern** ändert die Ausgabe des Charakters"
+ "\n\n- **Anforderungsdaten ändern** ändert die aktuellen Chat-Daten beim Senden"
+ "\n\n- **Anzeige ändern** ändert nur den Text bei der Anzeige, ohne Chat-Daten zu ändern"
+ "\n\nIN muss ein RegEx ohne Flags und ohne Schrägstriche am Anfang und Ende sein.\n\nOUT ist eine Zeichenfolge, die Ersetzungsmuster enthalten kann. Dies sind die Muster:"
+ "\n\n- $$\n\n - fügt $ ein"
+ "\n\n- $&\n\n - fügt den übereinstimmenden Teilstring ein"
+ "\n\n- $`\n\n - fügt den Teil der Zeichenfolge ein, der dem übereinstimmenden Teilstring vorausgeht"
+ "\n\n- $1\n\n - fügt die erste übereinstimmende Gruppe ein. funktioniert mit anderen Nummern wie 2, 3..."
+ "\n\n- $(name)\n\n - fügt die benannte Gruppe ein\n\nWenn OUT mit **@@** beginnt, ersetzt es nicht die Zeichenfolge, sondern führt stattdessen eine spezielle Wirkung aus, wenn eine übereinstimmende Zeichenfolge gefunden wird"
+ "\n\n- @@emo (Emotionsname)\n\n - wenn der Charakter den Emotion Images Modus verwendet, wird (Emotionsname) als Emotion festgelegt und die Standardoption verhindert",
+ "\n\n- **Eingabe ändern** ändert die Eingabe des Benutzers"
+ "\n\n- **Ausgabe ändern** ändert die Ausgabe des Charakters"
+ "\n\n- **Anforderungsdaten ändern** ändert die aktuellen Chat-Daten beim Senden"
+ "\n\n- **Anzeige ändern** ändert nur den Text bei der Anzeige, ohne Chat-Daten zu ändern"
+ "\n\nIN muss ein RegEx ohne Flags und ohne Schrägstriche am Anfang und Ende sein.\n\nOUT ist eine Zeichenfolge, die Ersetzungsmuster enthalten kann. Dies sind die Muster:"
+ "\n\n- $$\n\n - fügt $ ein"
+ "\n\n- $&\n\n - fügt den übereinstimmenden Teilstring ein"
+ "\n\n- $`\n\n - fügt den Teil der Zeichenfolge ein, der dem übereinstimmenden Teilstring vorausgeht"
+ "\n\n- $1\n\n - fügt die erste übereinstimmende Gruppe ein. funktioniert mit anderen Nummern wie 2, 3..."
+ "\n\n- $(name)\n\n - fügt die benannte Gruppe ein\n\nWenn OUT mit **@@** beginnt, ersetzt es nicht die Zeichenfolge, sondern führt stattdessen eine spezielle Wirkung aus, wenn eine übereinstimmende Zeichenfolge gefunden wird"
+ "\n\n- @@emo (Emotionsname)\n\n - wenn der Charakter den Emotion Images Modus verwendet, wird (Emotionsname) als Emotion festgelegt und die Standardoption verhindert",
experimental: "Dies ist ein experimentelles Feature und könnte instabil sein",
oogaboogaURL: "Wenn Ihre WebUI nur eine ältere Version der API unterstützt, sollte Ihre URL in etwa so aussehen *https:.../run/textgen*"
+ "\n\nWenn Ihre WebUI die neue Version der API unterstützt, sollte Ihre URL in etwa so aussehen *https://.../api/v1/generate* und den API-Server als Host verwenden sowie --api als Argument hinzufügen",
+ "\n\nWenn Ihre WebUI die neue Version der API unterstützt, sollte Ihre URL in etwa so aussehen *https://.../api/v1/generate* und den API-Server als Host verwenden sowie --api als Argument hinzufügen",
exampleMessage: "Beispielgespräche, die die Ausgabe des Charakters beeinflussen. Es werden keine Tokens dauerhaft verwendet."
+ "\n\nBeispielformat von Gesprächen:"
+ "\n\n```\n<START>\n{{user}}: hi\n{{char}}: hallo\n<START>\n{{user}}: hi\nHaruhi: hallo\n```"
+ "\n\n```<START>``` markiert den Beginn eines neuen Gesprächs",
+ "\n\nBeispielformat von Gesprächen:"
+ "\n\n```\n<START>\n{{user}}: hi\n{{char}}: hallo\n<START>\n{{user}}: hi\nHaruhi: hallo\n```"
+ "\n\n```<START>``` markiert den Beginn eines neuen Gesprächs",
creatorQuotes: "Beachten Sie, dass diese Anmkerung oberhalb der ersten Nachricht angezeigt wird. Sie wird verwendet, um den Benutzer über diesen Charakter zu informieren. Diese Anmerkung wird nicht in die Anweisungen eingespielt und hat deshalb keine Auswirkung auf die Antwort der KI.",
systemPrompt: "Eine Anweisung, mit der die Haupt-Anweisung aus den Einstellungen ersetzt wird, sofern das Feld nicht leer ist",
@@ -85,9 +85,9 @@ export const languageGerman = {
loreRandomActivation: "Wenn die Bedingung 'Wahrscheinlichkeit verwenden' aktiviert ist, wird der Kontext mit einer festgelegten Wahrscheinlichkeit, die durch 'Wahrscheinlichkeit' festgelegt wird, jedes Mal aktiviert, wenn eine Chat-Nachricht gesendet wird und die anderen Bedingungen der Überlieferung alle erfüllt sind",
additionalAssets: "Zusätzliche Assets, die in Ihrem Chat angezeigt werden sollen. \n\n - verwenden Sie `{{raw::<asset name>}}` um als Pfad zu verwenden.\n verwenden Sie `{{image::<asset name>}}` um als Bild zu verwenden\n - verwenden Sie `{{video::<asset name>}}` um als Video zu verwenden\n verwenden Sie `{{audio::<asset name>}}` um als Audio zu verwenden\n es wird empfohlen, dies im HTML Backend einzufügen",
superMemory: "SupaMemory ermöglicht es Ihrem Charakter, sich mehr Informationen zu 'merken', indem der KI zusammengefasste Daten zugeführt werden.\n\n"
+ "Das SupaMemory-Modell ist ein Modell, das die Zusammenfassung für einen Text erstellt. Davinci oder GPT-3.5-16k werden empfohlen. Hilfsmodelle hingegen werden nicht empfohlen, es sei denn, es handelt sich um ein ungefiltertes Modell mit mindestens 2000 Tokens Kontextgröße und einer ausgereiften Fähigkeiten, Texte zusammenfassen zu können.\n\n"
+ "Die SupaMemory-Anweisung entscheidet darüber, welche Anweisung konkret zur Zusammenfassung gesendet werden soll. Wenn Sie das Feld leer lassen, wird die Standard-Anweisung verwendet. Es wird empfohlen, es leer zu lassen.\n\n"
+ "Nachdem alles eingerichtet ist, können Sie SupaMemory in den Einstellungen eines Charakters aktivieren",
+ "Das SupaMemory-Modell ist ein Modell, das die Zusammenfassung für einen Text erstellt. Davinci oder GPT-3.5-16k werden empfohlen. Hilfsmodelle hingegen werden nicht empfohlen, es sei denn, es handelt sich um ein ungefiltertes Modell mit mindestens 2000 Tokens Kontextgröße und einer ausgereiften Fähigkeiten, Texte zusammenfassen zu können.\n\n"
+ "Die SupaMemory-Anweisung entscheidet darüber, welche Anweisung konkret zur Zusammenfassung gesendet werden soll. Wenn Sie das Feld leer lassen, wird die Standard-Anweisung verwendet. Es wird empfohlen, es leer zu lassen.\n\n"
+ "Nachdem alles eingerichtet ist, können Sie SupaMemory in den Einstellungen eines Charakters aktivieren",
replaceGlobalNote: "Sofern dieses Feld ausgefüllt ist, wird es die aktuelle globale Notiz ersetzen",
backgroundHTML: "Ein Markdown/HTML-Datenblock, der im Backend der Chat-Ausgabe hinzugefügt wird.\n\n Sie können auch zusätzliche Assets verwenden. Zum Beispiel können Sie `{{audio::<Asset-Name}}` für Hintergrundmusik verwenden."
+ "\n\n Zusätzlich können Sie dies mit weiteren Assets verwenden:"
@@ -291,7 +291,8 @@ export const languageGerman = {
globalLoreBook: 'Lore Buch',
globalRegexScript: "Regex",
accessibility: "Barrierefreiheit",
sendWithEnter: "Mit Enter senden",
sendWithEnter: "Mit Enter senden(Umschalt + Enter beim Entpacken zu senden)",
fixedChatTextarea: "Unten im Chatfenster fixieren",
clickToEdit: "Text zum Bearbeiten anklicken",
setNodePassword: "Legen Sie Ihr Passwort für die Sicherheit fest",
inputNodePassword: "Geben Sie Ihr Passwort ein. Wenn Sie sich nicht erinnern können, entfernen Sie save/__password.txt in Ihren Serverdateien und starten Sie den Server neu",

View File

@@ -59,31 +59,31 @@ export const languageEnglish = {
emotion: "Emotion Images option shows image depending at character's emotion which is analized by character's response. you must input emotion name as words *(like joy, happy, fear and etc.)* .emotion named **neutral** will be default emotion if it exists. must be more then 3 images to work properly.",
imggen: "After analyzing the chat, apply the prompt to {{slot}}.",
regexScript: "Regex Script is a custom regex that replaces string that matches IN to OUT.\n\nThere four type options."
+ "\n\n- **Modify Input** modifys user's input"
+ "\n\n- **Modify Output** modifys character's output"
+ "\n\n- **Modify Request Data** modifys current chat data when sent."
+ "\n\n- **Modify Display** just modifies the text when shown without modifying chat data."
+ "\n\nIN must be a regex without flags and without slashes in start and end.\n\nOUT is a string which can include replacement patterns. these are the patterns:"
+ "\n\n- $$\n\n - inserts $"
+ "\n\n- $&\n\n - inserts the matched substring."
+ "\n\n- $`\n\n - inserts the portion of the string that precedes the matched substring."
+ "\n\n- $1\n\n - inserts the first matching group. works with other number like 2, 3..."
+ "\n\n- $(name)\n\n - inserts the named group"
+ "\n\nFor flags, you can not only use native supported flags, but also use these flags, which are designed for advanced users:"
+ "\n\n- `<inject>` - injects the result to the current string."
+ "\n- `<move_top>` - moves the result to the top of the string."
+ "\n- `<move_bottom>` - moves the result to the bottom of the string."
+ "\n- `<repeat_back>` - if the match is not found, it carries the result from the previous match."
+ "\n- `<order n>` - sets the order of the result. higher order will be shown first. `n` is a number. (like `<order 1>`) if this flag is not set, it will be set to 0."
+ "\n- `<cbs>` - parses curly braced synatxes in IN."
+ "\n\nTo use with native flags, you can use like `gi<cbs><move_top>`.",
+ "\n\n- **Modify Input** modifys user's input"
+ "\n\n- **Modify Output** modifys character's output"
+ "\n\n- **Modify Request Data** modifys current chat data when sent."
+ "\n\n- **Modify Display** just modifies the text when shown without modifying chat data."
+ "\n\nIN must be a regex without flags and without slashes in start and end.\n\nOUT is a string which can include replacement patterns. these are the patterns:"
+ "\n\n- $$\n\n - inserts $"
+ "\n\n- $&\n\n - inserts the matched substring."
+ "\n\n- $`\n\n - inserts the portion of the string that precedes the matched substring."
+ "\n\n- $1\n\n - inserts the first matching group. works with other number like 2, 3..."
+ "\n\n- $(name)\n\n - inserts the named group"
+ "\n\nFor flags, you can not only use native supported flags, but also use these flags, which are designed for advanced users:"
+ "\n\n- `<inject>` - injects the result to the current string."
+ "\n- `<move_top>` - moves the result to the top of the string."
+ "\n- `<move_bottom>` - moves the result to the bottom of the string."
+ "\n- `<repeat_back>` - if the match is not found, it carries the result from the previous match."
+ "\n- `<order n>` - sets the order of the result. higher order will be shown first. `n` is a number. (like `<order 1>`) if this flag is not set, it will be set to 0."
+ "\n- `<cbs>` - parses curly braced synatxes in IN."
+ "\n\nTo use with native flags, you can use like `gi<cbs><move_top>`.",
experimental: "This is a experimental feature. it might be unstable.",
oogaboogaURL: "If your WebUI supports older version of api, your url should look *like https:.../run/textgen*\n\n"
+ "If your WebUI supports newVersion of api, your url should look like *https://.../api/v1/generate* and use the api server as host, and add --api to arguments.",
+ "If your WebUI supports newVersion of api, your url should look like *https://.../api/v1/generate* and use the api server as host, and add --api to arguments.",
exampleMessage: "Example conversations that effects output of the character. it dosen't uses tokens permanently."
+ "\n\nExample format of conversations:"
+ "\n\n```\n<START>\n{{user}}: hi\n{{char}}: hello\n<START>\n{{user}}: hi\nHaruhi: hello\n```"
+ "\n\n```<START>``` Marks the beginning of a new conversation.",
+ "\n\nExample format of conversations:"
+ "\n\n```\n<START>\n{{user}}: hi\n{{char}}: hello\n<START>\n{{user}}: hi\nHaruhi: hello\n```"
+ "\n\n```<START>``` Marks the beginning of a new conversation.",
creatorQuotes: "Note that appearances on top of first message. Used to inform users about this character. It doesn't go into prompt.",
systemPrompt: "A prompt that replaces main prompt in settings if its not blank.",
chatNote: "a note that strongly effects model behavior. embbedded to current chat. also known as memory or ujb.",
@@ -94,9 +94,9 @@ export const languageEnglish = {
loreRandomActivation: "If Use Probability Condition is abled, if the lore's other conditions are all met, the lore will be activated with a set probability which is set by 'Probability' each time a chat is sent.",
additionalAssets: "Additional assets to display in your chat. \n\n - use `{{raw::<asset name>}}` to use as path.\n - use `{{image::<asset name>}}` to use as image\n - use `{{video::<asset name>}}` to use as video\n - use `{{audio::<asset name>}}` to use as audio\n - recommended to put in Background HTML",
superMemory: "SuperMemory makes your character memorize more by giving summarized data to AI.\n\n"
+ "SuperMemory model is a model that summarizes that text. davinci is recommended, and Auxiliary models are not recommended unless it is an unfiltered model with over 2000 tokens with great summarizing skill.\n\n"
+ "SuperMemory Prompt decides what prompt should be sent to summarize. if you leave it blank, it will use the default prompt. leaving blank is recommended.\n\n"
+ "After it is all setup, you can able it in the setting of a character.",
+ "SuperMemory model is a model that summarizes that text. davinci is recommended, and Auxiliary models are not recommended unless it is an unfiltered model with over 2000 tokens with great summarizing skill.\n\n"
+ "SuperMemory Prompt decides what prompt should be sent to summarize. if you leave it blank, it will use the default prompt. leaving blank is recommended.\n\n"
+ "After it is all setup, you can able it in the setting of a character.",
replaceGlobalNote: "If its not blank, it replaces current global note to this.",
backgroundHTML: "A Markdown/HTML Data that would be injected to the background of chat screen.\n\n you can also use additional assets. for example, you can use `{{audio::<asset name}}` for background music."
+ "\n\n Additionaly, you can use these with additional assets:"
@@ -147,17 +147,17 @@ export const languageEnglish = {
betaMobileGUI: "If enabled, it will use beta mobile GUI on small (less than 800px) screens. requires refresh.",
unrecommended: "This is a unrecommended setting. it is not recommended to use this setting.",
jsonSchema: "This is a JSON Schema that will be sent to the AI model if AI model supports JSON Schema.\n\nHowever, since JSON Schema is hard to learn, In RisuAI, you can use subset of TypeScript interface instead of JSON Schema. RisuAI will convert it in runtime." +
"For example, if you want to send a JSON like this:\n\n```js\n{\n \"name\": \"RisuAI\", //name must be RisuAI,\n \"age\": 1, //age must be number,\n \"icon\": \"slim\", //icon must be \'slim\' or 'rounded'\n \"thoughts\": [\"Good View!\", \"Lorem\"] //thoughts must be array of strings\n}\n```\n\n" +
"You can put this TypeScript interface:\n\n```typescript\ninterface Schema {\n name: string;\n age: number;\n icon: \'slim\'|\'rounded\'\n thoughts: string[]\n}\n```\n\n" +
"Name of the interface doesn't matter. for more information, see the typescript documentation. (https://www.typescriptlang.org/docs/handbook/interfaces.html), and to Check what subset of TypeScript is supported, see the below." +
"<details><summary>Supported TypeScript Subset</summary>\n\n" +
`Supported types are \`boolean\`, \`number\`, \`string\`, \`Array\`. Advanced typing like unit types, intersection types, union types, optional, literal types, and etc. are not supported except for these cases:\n
"For example, if you want to send a JSON like this:\n\n```js\n{\n \"name\": \"RisuAI\", //name must be RisuAI,\n \"age\": 1, //age must be number,\n \"icon\": \"slim\", //icon must be \'slim\' or 'rounded'\n \"thoughts\": [\"Good View!\", \"Lorem\"] //thoughts must be array of strings\n}\n```\n\n" +
"You can put this TypeScript interface:\n\n```typescript\ninterface Schema {\n name: string;\n age: number;\n icon: \'slim\'|\'rounded\'\n thoughts: string[]\n}\n```\n\n" +
"Name of the interface doesn't matter. for more information, see the typescript documentation. (https://www.typescriptlang.org/docs/handbook/interfaces.html), and to Check what subset of TypeScript is supported, see the below." +
"<details><summary>Supported TypeScript Subset</summary>\n\n" +
`Supported types are \`boolean\`, \`number\`, \`string\`, \`Array\`. Advanced typing like unit types, intersection types, union types, optional, literal types, and etc. are not supported except for these cases:\n
- Array of primitive types: (ex. \`string[]\`, \`Array<boolean>)\`
- Unit types between strings: (ex. \`'slim'|'rounded'\`).
Properties must be one in a line. if there is multiple properties in a line, it will throw an error. Properties and name of the interface must be only in latin characters, in ASCII range. name of the properties must not be surrounded by quotes or double quotes. Nesting inside the interface is not supported. it is not allowed to put \`{\` or \`}\` in the line that properties are defined. If you want to use more advanced types, use JSON Schema instead.
` +
"</details>"
"</details>"
,
strictJsonSchema: "If enabled, it will strictly follow the Provided Schema for JSON on some models. if it is disabled, it may ignore the JSON Schema.",
extractJson: "If it is not blank, it will extract specific JSON data from the response. for example, if you want to extract `response.text[0]` in response `{\"response\": {\"text\": [\"hello\"]}}`, you can put `response.text.0`.",
@@ -219,7 +219,7 @@ export const languageEnglish = {
setupMessageOption1Desc: "Recommended for new users",
setupMessageOption2: "I will setup myself",
claudeDesc: "Claude is a AI model made by Antropic, competitor to OpenAI. its better than GPT if you want to use it in other languages than English.",
openAIDesc: "OpenAI GPT is a high quality AI model, but it is paid and filtered, and weak in other than English.",
openAIDesc: "OpenAI GPT is a high quality AI model, but it is paid and filtered, and weak in other than English.",
chooseChatType: "Great! Now select the chat language.",
chooseChatTypeOption1: "Full English",
chooseChatTypeOption1Desc: "This will make AI to use English and input/output in English. Recommended for English speakers.",
@@ -570,6 +570,7 @@ export const languageEnglish = {
globalRegexScript: "Global Regex",
accessibility: "Accessibility",
sendWithEnter: "Send with Enter Key",
fixedChatTextarea: "Fixed at the bottom of the chat window(When unchecked, Shift + Enter changes to send a message.)",
clickToEdit: "Click Text to Edit",
setNodePassword: "Set your password to security",
inputNodePassword: "Input your password. if you can't remember, remove save/__password.txt in your server files and restart the server.",

View File

@@ -341,7 +341,8 @@ export const languageSpanish = {
globalLoreBook: 'Libro de Lore Global',
globalRegexScript: "Regex Global",
accessibility: "Accesibilidad",
sendWithEnter: "Enviar con la Tecla Enter",
sendWithEnter: "Enviar con la Tecla Enter(Al desactivar la verificación, Shift + Enter cambia a Transmisión de Mensajes.)",
fixedChatTextarea: "Fijación en la parte inferior de la ventana de chat",
clickToEdit: "Haz Clic en el Texto para Editar",
setNodePassword: "Establece tu contraseña para la seguridad",
inputNodePassword: "Ingresa tu contraseña. si no la recuerdas, elimina save/__password.txt en tus archivos de servidor y reinicia el servidor.",

View File

@@ -517,7 +517,8 @@ export const languageKorean = {
"globalLoreBook": "글로벌 로어북",
"globalRegexScript": "글로벌 정규식",
"accessibility": "접근성",
"sendWithEnter": "엔터키로 메세지 보내기",
"sendWithEnter": "엔터키로 메세지 보내기(체크 해제시 Shift + Enter가 메세지 전송으로 변경.)",
"fixedChatTextarea": "채팅창 하단 고정",
"clickToEdit": "클릭해서 수정하기",
"setNodePassword": "보안을 위해 비밀번호를 정해주세요",
"inputNodePassword": "비밀번호를 입력해주세요. 기억이 안나신다면, save/__password를 지우고 서버를 재시작해주세요.",

View File

@@ -1,83 +1,83 @@
export const LanguageVietnamese = {
"formating": {
"main": "Lời nhắc chính",
"jailbreak": "Lời nhắc bẻ khóa",
"chats": "Cuộc trò chuyện trước đây",
"lorebook": "Sách truyền thuyết",
"globalNote": "Ghi chú chung",
"authorNote": "Ghi chú của tác giả",
"lastChat": "Cuộc trò chuyện cuối cùng",
"description": "Mô tả nhân vật",
"personaPrompt": "Lời nhắc của Persona",
"plain": "Lời nhắc đơn giản",
"memory": "Bộ nhớ Supa/Hypa"
"main": "Lời nhắc chính",
"jailbreak": "Lời nhắc bẻ khóa",
"chats": "Cuộc trò chuyện trước đây",
"lorebook": "Sách truyền thuyết",
"globalNote": "Ghi chú chung",
"authorNote": "Ghi chú của tác giả",
"lastChat": "Cuộc trò chuyện cuối cùng",
"description": "Mô tả nhân vật",
"personaPrompt": "Lời nhắc của Persona",
"plain": "Lời nhắc đơn giản",
"memory": "Bộ nhớ Supa/Hypa"
},
"errors": {
"toomuchtoken": "Lỗi: Mã thông báo bắt buộc tối thiểu lớn hơn Kích thước ngữ cảnh tối đa.",
"unknownModel": "Lỗi: Đã chọn mô hình không xác định",
"httpError": "Lỗi: lỗi trong yêu cầu:",
"noData": "Không có dữ liệu trong tệp hoặc tệp bị hỏng",
"onlyOneChat": "Phải có ít nhất một cuộc trò chuyện",
"alreadyCharInGroup": "Đã có một nhân vật có cùng tên trong nhóm.",
"noUserIcon": "Bạn phải đặt biểu tượng của mình trước."
"toomuchtoken": "Lỗi: Mã thông báo bắt buộc tối thiểu lớn hơn Kích thước ngữ cảnh tối đa.",
"unknownModel": "Lỗi: Đã chọn mô hình không xác định",
"httpError": "Lỗi: lỗi trong yêu cầu:",
"noData": "Không có dữ liệu trong tệp hoặc tệp bị hỏng",
"onlyOneChat": "Phải có ít nhất một cuộc trò chuyện",
"alreadyCharInGroup": "Đã có một nhân vật có cùng tên trong nhóm.",
"noUserIcon": "Bạn phải đặt biểu tượng của mình trước."
},
"showHelp": "Hiển thị trợ giúp",
"help": {
"model": "Tùy chọn mô hình là mô hình chính được sử dụng trong trò chuyện.",
"submodel": "Mô hình phụ trợ là mô hình được sử dụng để phân tích hình ảnh cảm xúc và đề xuất tự động, v.v. Nên sử dụng gpt3.5.",
"oaiapikey": "Khóa Api cho OpenAI. bạn có thể lấy nó ở https://platform.openai.com/account/api-keys",
"mainprompt": "Tùy chọn lời nhắc chính đặt hành vi mô hình mặc định.",
"jailbreak": "Tùy chọn lời nhắc jailbreak kích hoạt khi nút chuyển đổi jailbreak được bật.",
"globalNote": "một lưu ý có tác động mạnh mẽ đến hành vi của mô hình, còn được gọi là UJB. hoạt động ở tất cả các ký tự.",
"autoSuggest": "Lời nhắc được sử dụng để tạo các tùy chọn khi tự động đề xuất phản hồi của người dùng.",
"formatOrder": "thứ tự hình thành của lời nhắc. các khối thấp hơn sẽ có hiệu quả hơn đối với mô hình.",
"forceUrl": "nếu nó không trống, yêu cầu sẽ chuyển đến url mà bạn đã nhập.",
"tempature": "giá trị thấp hơn làm cho nhân vật tuân theo lời nhắc một cách chặt chẽ, nhưng nó sẽ có nhiều khả năng phản hồi giống như một cái máy hơn.\nGiá trị cao hơn sẽ dẫn đến hành vi sáng tạo, nhưng phản ứng của nhân vật có thể dễ dàng bị phá vỡ hơn.",
"frequencyPenalty": "Giá trị cao hơn ngăn chặn việc sử dụng các từ trùng lặp trong phản hồi, nhưng phản hồi của nhân vật có thể dễ dàng bị hỏng hơn.",
"presensePenalty": "Giá trị cao hơn sẽ ngăn chặn việc sử dụng các từ trùng lặp trong mọi ngữ cảnh, nhưng phản hồi của nhân vật có thể dễ bị phân tích hơn.",
"sdProvider": "nhà cung cấp để tạo hình ảnh.",
"msgSound": "Phát âm thanh *ding* khi nhân vật phản hồi",
"charDesc": "Mô tả ngắn gọn về nhân vật. điều này ảnh hưởng đến phản ứng của nhân vật.",
"charFirstMessage": "Tin nhắn đầu tiên của nhân vật. điều này ảnh hưởng lớn đến phản ứng của nhân vật.",
"charNote": "một lưu ý có ảnh hưởng mạnh mẽ đến hành vi của mô hình. được nhúng vào ký tự hiện tại. còn được gọi là UJB.",
"toggleNsfw": "bật và tắt lời nhắc jailbreak.",
"lorebook": "Lorebook là một từ điển do người dùng tạo ra cho AI. AI chỉ nhìn thấy nó khi khóa kích hoạt ở đâu trong ngữ cảnh.",
"loreName": "tên của truyền thuyết. nó không ảnh hưởng đến Ai.",
"loreActivationKey": "Nếu một trong các khóa kích hoạt tồn tại trong ngữ cảnh, truyền thuyết sẽ được kích hoạt và lời nhắc sẽ xuất hiện, được phân tách bằng dấu phẩy.",
"loreorder": "Nếu chèn Thứ tự cao hơn, nó sẽ ảnh hưởng đến mô hình nhiều hơn và nó sẽ ít bị cắt hơn khi truyền thuyết được kích hoạt nhiều.",
"bias": "thiên vị là dữ liệu khóa-giá trị sửa đổi khả năng xuất hiện của chuỗi.\nnó có thể là -100 đến 100, các giá trị cao hơn sẽ có nhiều khả năng xuất hiện hơn và các giá trị thấp hơn sẽ khó xuất hiện hơn\nCảnh báo: nếu mã thông báo sai, nó sẽ không hoạt động bình thường.",
"emotion": "Tùy chọn Hình ảnh Cảm xúc hiển thị hình ảnh tùy theo cảm xúc của nhân vật và được phân tích theo phản ứng của nhân vật. bạn phải nhập tên cảm xúc dưới dạng các từ *(như niềm vui, hạnh phúc, sợ hãi, v.v.)* .cảm xúc có tên **trung tính** sẽ là cảm xúc mặc định nếu nó tồn tại. phải có nhiều hơn 3 hình ảnh để hoạt động bình thường.",
"imggen": "Tùy chọn Tạo hình ảnh tạo và hiển thị hình ảnh từ chương trình bên ngoài. hình ảnh được tạo bởi dấu nhắc hình ảnh, được tạo bằng cách phân tích cuộc trò chuyện hiện tại.\n\n việc tạo hình ảnh được phân tích dựa trên các đối số khóa-giá trị, có thể định cấu hình ở bên dưới.\nPhím Zn**'always'** luôn được áp dụng và không thay đổi. Phím **'âm'** luôn áp dụng giá trị âm để tạo hình ảnh.\n\ncác đối tượng có giá trị của khóa khác sẽ thay đổi theo tên của khóa khi cuộc trò chuyện diễn ra.\n\nNếu một phím có ký tự đặc biệt ở phía trước tên của nó thì phím đó có tác dụng đặc biệt.\n- nếu khóa bắt đầu bằng **|**, giá trị của khóa sẽ không thay đổi.\n- nếu khóa bắt đầu bằng *******, giá trị của khóa sẽ có nhiều khả năng thay đổi hơn.\n\nkhi hình ảnh được tạo lần đầu tiên, bạn chỉ có thể thay đổi nó bằng cách sửa đổi 'Dữ liệu tạo hình ảnh hiện tại' ở bên dưới.",
"regexScript": "Regex Script là tập lệnh tùy chỉnh thay thế chuỗi khớp IN với OUT.\n\nCó bốn lựa chọn loại.\n\n- **Sửa đổi đầu vào** sửa đổi đầu vào của người dùng\n\n- **Sửa đổi đầu ra** sửa đổi đầu ra của ký tự\n\n- **Sửa đổi dữ liệu yêu cầu** sửa đổi dữ liệu trò chuyện hiện tại khi được gửi.\n\n- **Sửa đổi hiển thị** chỉ sửa đổi văn bản khi được hiển thị mà không sửa đổi dữ liệu trò chuyện.\n\nIN phải là biểu thức chính quy không có cờ và không có dấu gạch chéo ở đầu và cuối.\n\nOUT là một chuỗi có thể bao gồm các mẫu thay thế. đây là những mẫu:\n\n- $$\n\n - chèn $\n\n- $&\n\n - chèn chuỗi con phù hợp.\n\n- $`\n\n - chèn phần chuỗi đứng trước chuỗi con phù hợp.\n\n- 1$\n\n - chèn nhóm phù hợp đầu tiên. làm việc với số khác như 2, 3...\n\n- $(tên)\n\n - chèn nhóm được đặt tên\n\nNếu OUT bắt đầu bằng **@@**, nó không thay thế chuỗi mà thay vào đó tạo ra hiệu ứng đặc biệt nếu tìm thấy chuỗi trùng khớp.\n\n- @@emo (tên cảm xúc)\n\n - nếu nhân vật ở chế độ Hình ảnh Cảm xúc, hãy đặt (tên cảm xúc) làm cảm xúc và ngăn mặc định.",
"experimental": "Đây là một tính năng thử nghiệm. nó có thể không ổn định.",
"oogaboogaURL": "Nếu WebUI của bạn hỗ trợ phiên bản api cũ hơn thì url của bạn sẽ trông *như https:.../run/textgen*\n\nNếu WebUI của bạn hỗ trợ Phiên bản mới của api thì url của bạn sẽ trông giống như *https://.../api/v1/generate* và sử dụng máy chủ api làm máy chủ lưu trữ, đồng thời thêm --api vào đối số.",
"exampleMessage": "Các cuộc hội thoại ví dụ ảnh hưởng đến đầu ra của nhân vật. nó không sử dụng mã thông báo vĩnh viễn.\n\nĐịnh dạng ví dụ của cuộc hội thoại:\n\n```\n<BẮT ĐẦU>\n{{user}}: xin chào\n{{char}}: xin chào\n<BẮT ĐẦU>\n{{user}}: xin chào\nHaruhi: xin chào\n```\n\n```<START>``` Đánh dấu sự bắt đầu của một cuộc trò chuyện mới.",
"creatorQuotes": "Lưu ý rằng xuất hiện trên đầu tin nhắn đầu tiên. Được sử dụng để thông báo cho người dùng về nhân vật này. Nó không đi vào dấu nhắc.",
"systemPrompt": "Lời nhắc thay thế lời nhắc chính trong cài đặt nếu nó không trống.",
"chatNote": "một lưu ý có ảnh hưởng mạnh mẽ đến hành vi của mô hình. được nhúng vào cuộc trò chuyện hiện tại. còn được gọi là bộ nhớ hoặc ujb.",
"personality": "Mô tả ngắn gọn về tính cách nhân vật.\n\n**Không nên sử dụng tùy chọn này. Thay vào đó hãy mô tả nó bằng phần mô tả nhân vật.**",
"scenario": "Một mô tả ngắn gọn về kịch bản của nhân vật.\n\n**Không nên sử dụng tùy chọn này. Thay vào đó hãy mô tả nó bằng phần mô tả nhân vật.**",
"loreSelective": "Nếu chế độ Chọn lọc được bật, cả Khóa kích hoạt và Khóa phụ phải khớp nhau để kích hoạt truyền thuyết.",
"loreRandomActivation": "Nếu Điều kiện Xác suất Sử dụng được kích hoạt, nếu tất cả các điều kiện khác của truyền thuyết đều được đáp ứng, truyền thuyết sẽ được kích hoạt với một xác suất đã đặt được đặt bởi 'Xác suất' mỗi lần trò chuyện được gửi.",
"additionalAssets": "Nội dung bổ sung để hiển thị trong cuộc trò chuyện của bạn.\n\n - sử dụng `{{raw::<asset name>}}` để dùng làm đường dẫn.\n - sử dụng `{{img::<asset name>}}` để sử dụng làm hình ảnh\n - sử dụng `{{video::<asset name>}}` để sử dụng làm video\n - sử dụng `{{audio::<asset name>}}` để sử dụng làm âm thanh\n - nên đặt HTML nền",
"superMemory": "SuperMemory giúp nhân vật của bạn ghi nhớ nhiều hơn bằng cách cung cấp dữ liệu tóm tắt cho AI.\n\nMô hình SuperMemory là mô hình tóm tắt văn bản đó. davinci được khuyến nghị và các mô hình phụ trợ không được khuyến nghị trừ khi đó là mô hình chưa được lọc với hơn 2000 mã thông báo có kỹ năng tóm tắt tuyệt vời.\n\nLời nhắc SuperMemory quyết định lời nhắc nào sẽ được gửi để tóm tắt. nếu bạn để trống, nó sẽ sử dụng lời nhắc mặc định. nên để trống.\n\nSau khi thiết lập xong, bạn có thể sử dụng nó trong cài đặt của một nhân vật.",
"replaceGlobalNote": "Nếu nó không trống, nó sẽ thay thế ghi chú chung hiện tại bằng ghi chú này.",
"backgroundHTML": "Dữ liệu Markdown/HTML sẽ được đưa vào nền màn hình trò chuyện.\n\n bạn cũng có thể sử dụng tài sản bổ sung. ví dụ: bạn có thể sử dụng `{{audio::<asset name}}` cho nhạc nền.\n\n Ngoài ra, bạn có thể sử dụng những thứ này với các nội dung bổ sung:\n - `{{bg::<asset name>}}`: thêm nền làm nội dung"
"model": "Tùy chọn mô hình là mô hình chính được sử dụng trong trò chuyện.",
"submodel": "Mô hình phụ trợ là mô hình được sử dụng để phân tích hình ảnh cảm xúc và đề xuất tự động, v.v. Nên sử dụng gpt3.5.",
"oaiapikey": "Khóa Api cho OpenAI. bạn có thể lấy nó ở https://platform.openai.com/account/api-keys",
"mainprompt": "Tùy chọn lời nhắc chính đặt hành vi mô hình mặc định.",
"jailbreak": "Tùy chọn lời nhắc jailbreak kích hoạt khi nút chuyển đổi jailbreak được bật.",
"globalNote": "một lưu ý có tác động mạnh mẽ đến hành vi của mô hình, còn được gọi là UJB. hoạt động ở tất cả các ký tự.",
"autoSuggest": "Lời nhắc được sử dụng để tạo các tùy chọn khi tự động đề xuất phản hồi của người dùng.",
"formatOrder": "thứ tự hình thành của lời nhắc. các khối thấp hơn sẽ có hiệu quả hơn đối với mô hình.",
"forceUrl": "nếu nó không trống, yêu cầu sẽ chuyển đến url mà bạn đã nhập.",
"tempature": "giá trị thấp hơn làm cho nhân vật tuân theo lời nhắc một cách chặt chẽ, nhưng nó sẽ có nhiều khả năng phản hồi giống như một cái máy hơn.\nGiá trị cao hơn sẽ dẫn đến hành vi sáng tạo, nhưng phản ứng của nhân vật có thể dễ dàng bị phá vỡ hơn.",
"frequencyPenalty": "Giá trị cao hơn ngăn chặn việc sử dụng các từ trùng lặp trong phản hồi, nhưng phản hồi của nhân vật có thể dễ dàng bị hỏng hơn.",
"presensePenalty": "Giá trị cao hơn sẽ ngăn chặn việc sử dụng các từ trùng lặp trong mọi ngữ cảnh, nhưng phản hồi của nhân vật có thể dễ bị phân tích hơn.",
"sdProvider": "nhà cung cấp để tạo hình ảnh.",
"msgSound": "Phát âm thanh *ding* khi nhân vật phản hồi",
"charDesc": "Mô tả ngắn gọn về nhân vật. điều này ảnh hưởng đến phản ứng của nhân vật.",
"charFirstMessage": "Tin nhắn đầu tiên của nhân vật. điều này ảnh hưởng lớn đến phản ứng của nhân vật.",
"charNote": "một lưu ý có ảnh hưởng mạnh mẽ đến hành vi của mô hình. được nhúng vào ký tự hiện tại. còn được gọi là UJB.",
"toggleNsfw": "bật và tắt lời nhắc jailbreak.",
"lorebook": "Lorebook là một từ điển do người dùng tạo ra cho AI. AI chỉ nhìn thấy nó khi khóa kích hoạt ở đâu trong ngữ cảnh.",
"loreName": "tên của truyền thuyết. nó không ảnh hưởng đến Ai.",
"loreActivationKey": "Nếu một trong các khóa kích hoạt tồn tại trong ngữ cảnh, truyền thuyết sẽ được kích hoạt và lời nhắc sẽ xuất hiện, được phân tách bằng dấu phẩy.",
"loreorder": "Nếu chèn Thứ tự cao hơn, nó sẽ ảnh hưởng đến mô hình nhiều hơn và nó sẽ ít bị cắt hơn khi truyền thuyết được kích hoạt nhiều.",
"bias": "thiên vị là dữ liệu khóa-giá trị sửa đổi khả năng xuất hiện của chuỗi.\nnó có thể là -100 đến 100, các giá trị cao hơn sẽ có nhiều khả năng xuất hiện hơn và các giá trị thấp hơn sẽ khó xuất hiện hơn\nCảnh báo: nếu mã thông báo sai, nó sẽ không hoạt động bình thường.",
"emotion": "Tùy chọn Hình ảnh Cảm xúc hiển thị hình ảnh tùy theo cảm xúc của nhân vật và được phân tích theo phản ứng của nhân vật. bạn phải nhập tên cảm xúc dưới dạng các từ *(như niềm vui, hạnh phúc, sợ hãi, v.v.)* .cảm xúc có tên **trung tính** sẽ là cảm xúc mặc định nếu nó tồn tại. phải có nhiều hơn 3 hình ảnh để hoạt động bình thường.",
"imggen": "Tùy chọn Tạo hình ảnh tạo và hiển thị hình ảnh từ chương trình bên ngoài. hình ảnh được tạo bởi dấu nhắc hình ảnh, được tạo bằng cách phân tích cuộc trò chuyện hiện tại.\n\n việc tạo hình ảnh được phân tích dựa trên các đối số khóa-giá trị, có thể định cấu hình ở bên dưới.\nPhím Zn**'always'** luôn được áp dụng và không thay đổi. Phím **'âm'** luôn áp dụng giá trị âm để tạo hình ảnh.\n\ncác đối tượng có giá trị của khóa khác sẽ thay đổi theo tên của khóa khi cuộc trò chuyện diễn ra.\n\nNếu một phím có ký tự đặc biệt ở phía trước tên của nó thì phím đó có tác dụng đặc biệt.\n- nếu khóa bắt đầu bằng **|**, giá trị của khóa sẽ không thay đổi.\n- nếu khóa bắt đầu bằng *******, giá trị của khóa sẽ có nhiều khả năng thay đổi hơn.\n\nkhi hình ảnh được tạo lần đầu tiên, bạn chỉ có thể thay đổi nó bằng cách sửa đổi 'Dữ liệu tạo hình ảnh hiện tại' ở bên dưới.",
"regexScript": "Regex Script là tập lệnh tùy chỉnh thay thế chuỗi khớp IN với OUT.\n\nCó bốn lựa chọn loại.\n\n- **Sửa đổi đầu vào** sửa đổi đầu vào của người dùng\n\n- **Sửa đổi đầu ra** sửa đổi đầu ra của ký tự\n\n- **Sửa đổi dữ liệu yêu cầu** sửa đổi dữ liệu trò chuyện hiện tại khi được gửi.\n\n- **Sửa đổi hiển thị** chỉ sửa đổi văn bản khi được hiển thị mà không sửa đổi dữ liệu trò chuyện.\n\nIN phải là biểu thức chính quy không có cờ và không có dấu gạch chéo ở đầu và cuối.\n\nOUT là một chuỗi có thể bao gồm các mẫu thay thế. đây là những mẫu:\n\n- $$\n\n - chèn $\n\n- $&\n\n - chèn chuỗi con phù hợp.\n\n- $`\n\n - chèn phần chuỗi đứng trước chuỗi con phù hợp.\n\n- 1$\n\n - chèn nhóm phù hợp đầu tiên. làm việc với số khác như 2, 3...\n\n- $(tên)\n\n - chèn nhóm được đặt tên\n\nNếu OUT bắt đầu bằng **@@**, nó không thay thế chuỗi mà thay vào đó tạo ra hiệu ứng đặc biệt nếu tìm thấy chuỗi trùng khớp.\n\n- @@emo (tên cảm xúc)\n\n - nếu nhân vật ở chế độ Hình ảnh Cảm xúc, hãy đặt (tên cảm xúc) làm cảm xúc và ngăn mặc định.",
"experimental": "Đây là một tính năng thử nghiệm. nó có thể không ổn định.",
"oogaboogaURL": "Nếu WebUI của bạn hỗ trợ phiên bản api cũ hơn thì url của bạn sẽ trông *như https:.../run/textgen*\n\nNếu WebUI của bạn hỗ trợ Phiên bản mới của api thì url của bạn sẽ trông giống như *https://.../api/v1/generate* và sử dụng máy chủ api làm máy chủ lưu trữ, đồng thời thêm --api vào đối số.",
"exampleMessage": "Các cuộc hội thoại ví dụ ảnh hưởng đến đầu ra của nhân vật. nó không sử dụng mã thông báo vĩnh viễn.\n\nĐịnh dạng ví dụ của cuộc hội thoại:\n\n```\n<BẮT ĐẦU>\n{{user}}: xin chào\n{{char}}: xin chào\n<BẮT ĐẦU>\n{{user}}: xin chào\nHaruhi: xin chào\n```\n\n```<START>``` Đánh dấu sự bắt đầu của một cuộc trò chuyện mới.",
"creatorQuotes": "Lưu ý rằng xuất hiện trên đầu tin nhắn đầu tiên. Được sử dụng để thông báo cho người dùng về nhân vật này. Nó không đi vào dấu nhắc.",
"systemPrompt": "Lời nhắc thay thế lời nhắc chính trong cài đặt nếu nó không trống.",
"chatNote": "một lưu ý có ảnh hưởng mạnh mẽ đến hành vi của mô hình. được nhúng vào cuộc trò chuyện hiện tại. còn được gọi là bộ nhớ hoặc ujb.",
"personality": "Mô tả ngắn gọn về tính cách nhân vật.\n\n**Không nên sử dụng tùy chọn này. Thay vào đó hãy mô tả nó bằng phần mô tả nhân vật.**",
"scenario": "Một mô tả ngắn gọn về kịch bản của nhân vật.\n\n**Không nên sử dụng tùy chọn này. Thay vào đó hãy mô tả nó bằng phần mô tả nhân vật.**",
"loreSelective": "Nếu chế độ Chọn lọc được bật, cả Khóa kích hoạt và Khóa phụ phải khớp nhau để kích hoạt truyền thuyết.",
"loreRandomActivation": "Nếu Điều kiện Xác suất Sử dụng được kích hoạt, nếu tất cả các điều kiện khác của truyền thuyết đều được đáp ứng, truyền thuyết sẽ được kích hoạt với một xác suất đã đặt được đặt bởi 'Xác suất' mỗi lần trò chuyện được gửi.",
"additionalAssets": "Nội dung bổ sung để hiển thị trong cuộc trò chuyện của bạn.\n\n - sử dụng `{{raw::<asset name>}}` để dùng làm đường dẫn.\n - sử dụng `{{img::<asset name>}}` để sử dụng làm hình ảnh\n - sử dụng `{{video::<asset name>}}` để sử dụng làm video\n - sử dụng `{{audio::<asset name>}}` để sử dụng làm âm thanh\n - nên đặt HTML nền",
"superMemory": "SuperMemory giúp nhân vật của bạn ghi nhớ nhiều hơn bằng cách cung cấp dữ liệu tóm tắt cho AI.\n\nMô hình SuperMemory là mô hình tóm tắt văn bản đó. davinci được khuyến nghị và các mô hình phụ trợ không được khuyến nghị trừ khi đó là mô hình chưa được lọc với hơn 2000 mã thông báo có kỹ năng tóm tắt tuyệt vời.\n\nLời nhắc SuperMemory quyết định lời nhắc nào sẽ được gửi để tóm tắt. nếu bạn để trống, nó sẽ sử dụng lời nhắc mặc định. nên để trống.\n\nSau khi thiết lập xong, bạn có thể sử dụng nó trong cài đặt của một nhân vật.",
"replaceGlobalNote": "Nếu nó không trống, nó sẽ thay thế ghi chú chung hiện tại bằng ghi chú này.",
"backgroundHTML": "Dữ liệu Markdown/HTML sẽ được đưa vào nền màn hình trò chuyện.\n\n bạn cũng có thể sử dụng tài sản bổ sung. ví dụ: bạn có thể sử dụng `{{audio::<asset name}}` cho nhạc nền.\n\n Ngoài ra, bạn có thể sử dụng những thứ này với các nội dung bổ sung:\n - `{{bg::<asset name>}}`: thêm nền làm nội dung"
},
"setup": {
"chooseProvider": "Chọn nhà cung cấp AI",
"openaikey": "OpenAI với Khóa API (Được khuyến nghị)",
"openaiProxy": "Proxy ngược OpenAI",
"setupmodelself": "Người khác/Tôi sẽ tự thiết lập",
"inputApiKey": "Nhập khóa API tại đây",
"apiKeyhelp": "Bạn có thể lấy khóa api từ:",
"setupSelfHelp": "Tự thiết lập trong cài đặt, sau khi màn hình Chào mừng kết thúc.",
"theme": "Chọn chủ đề của bạn",
"themeDescWifulike": "Không phù hợp với di động",
"themeDescWifuCut": "Thích hợp cho di động",
"themeDescClassic": "Thích hợp cho mọi thiết bị",
"texttheme": "Chọn màu văn bản của bạn",
"inputName": "Cuối cùng, nhập Biệt hiệu của bạn."
"chooseProvider": "Chọn nhà cung cấp AI",
"openaikey": "OpenAI với Khóa API (Được khuyến nghị)",
"openaiProxy": "Proxy ngược OpenAI",
"setupmodelself": "Người khác/Tôi sẽ tự thiết lập",
"inputApiKey": "Nhập khóa API tại đây",
"apiKeyhelp": "Bạn có thể lấy khóa api từ:",
"setupSelfHelp": "Tự thiết lập trong cài đặt, sau khi màn hình Chào mừng kết thúc.",
"theme": "Chọn chủ đề của bạn",
"themeDescWifulike": "Không phù hợp với di động",
"themeDescWifuCut": "Thích hợp cho di động",
"themeDescClassic": "Thích hợp cho mọi thiết bị",
"texttheme": "Chọn màu văn bản của bạn",
"inputName": "Cuối cùng, nhập Biệt hiệu của bạn."
},
"confirm": "Xác nhận",
"goback": "Quay lại",
@@ -262,7 +262,8 @@ export const LanguageVietnamese = {
"globalLoreBook": "Sách truyền thuyết toàn cầu",
"globalRegexScript": "Regex toàn cầu",
"accessibility": "Khả năng tiếp cận",
"sendWithEnter": "Gửi bằng phím Enter",
"sendWithEnter": "Gửi bằng phím Enter(Shift + Enter chuyển sang gửi tin nhắn khi không kiểm tra.)",
"fixedChatTextarea": "Cố định ở dưới khung chat",
"clickToEdit": "Bấm vào văn bản để chỉnh sửa",
"setNodePassword": "Đặt mật khẩu của bạn để bảo mật",
"inputNodePassword": "Nhập mật khẩu của bạn. nếu bạn không nhớ, hãy xóa save/__password.txt trong tệp máy chủ của bạn và khởi động lại máy chủ.",

View File

@@ -384,7 +384,8 @@ export const languageChineseTraditional = {
"globalLoreBook": "全域 Lorebook",
"globalRegexScript": "全域正規表達式",
"accessibility": "輔助功能",
"sendWithEnter": "使用 Enter 鍵發送",
"sendWithEnter": "使用 Enter 鍵發送取消检查时Shift + Enter更改为消息传送。",
"fixedChatTextarea": "固定聊天窗口底部",
"clickToEdit": "點擊文字進行編輯",
"setNodePassword": "設定密碼以提升安全性",
"inputNodePassword": "輸入密碼。如果忘記密碼,請刪除伺服器文件中的 save/__password.txt 並重啟伺服器。",

View File

@@ -1,12 +1,12 @@
<script lang="ts">
import Suggestion from './Suggestion.svelte';
import AdvancedChatEditor from './AdvancedChatEditor.svelte';
import Suggestion from './Suggestion.svelte';
import AdvancedChatEditor from './AdvancedChatEditor.svelte';
import { CameraIcon, DatabaseIcon, DicesIcon, GlobeIcon, ImagePlusIcon, LanguagesIcon, Laugh, MenuIcon, MicOffIcon, PackageIcon, Plus, RefreshCcwIcon, ReplyIcon, Send, StepForwardIcon, XIcon } from "lucide-svelte";
import { selectedCharID, PlaygroundStore, createSimpleCharacter } from "../../ts/stores.svelte";
import Chat from "./Chat.svelte";
import { type Message, type character, type groupChat } from "../../ts/storage/database.svelte";
import { DBState } from 'src/ts/stores.svelte';
import { DBState } from 'src/ts/stores.svelte';
import { getCharImage } from "../../ts/characters";
import { chatProcessStage, doingChat, sendChat } from "../../ts/process/index.svelte";
import { findCharacterbyId, getUserIconProtrait, messageForm, sleep } from "../../ts/util";
@@ -28,7 +28,7 @@
import { getInlayAsset } from 'src/ts/process/files/inlays';
import PlaygroundMenu from '../Playground/PlaygroundMenu.svelte';
import { ConnectionOpenStore } from 'src/ts/sync/multiuser';
import { coldStorageHeader, preLoadChat } from 'src/ts/process/coldstorage.svelte';
import { coldStorageHeader, preLoadChat } from 'src/ts/process/coldstorage.svelte';
let messageInput:string = $state('')
let messageInputTranslate:string = $state('')
@@ -168,7 +168,7 @@
sayingQu -= 1
if(sayingQu === 0){
break
}
}
}
let msg = cha.pop()
if(!msg){
@@ -258,15 +258,15 @@
}
}
interface Props {
openModuleList?: boolean;
openChatList?: boolean;
customStyle?: string;
}
let userIconProtrait = $state(false)
let currentUsername = $state(DBState.db.username)
let userIcon = $state(DBState.db.userIcon)
interface Props {
openModuleList?: boolean;
openChatList?: boolean;
customStyle?: string;
}
let userIconProtrait = $state(false)
let currentUsername = $state(DBState.db.username)
let userIcon = $state(DBState.db.userIcon)
$effect.pre(() =>{
@@ -287,7 +287,7 @@
userIcon = DBState.db.personas[DBState.db.selectedPersona].icon
})
let { openModuleList = $bindable(false), openChatList = $bindable(false), customStyle = '' }: Props = $props();
let { openModuleList = $bindable(false), openChatList = $bindable(false), customStyle = '' }: Props = $props();
let inputHeight = $state("44px")
let inputEle:HTMLTextAreaElement = $state()
let inputTranslateHeight = $state("44px")
@@ -380,7 +380,7 @@
canvases.reverse()
alertWait("Merging images...")
let mergedCanvas = document.createElement('canvas');
mergedCanvas.width = 0;
mergedCanvas.height = 0;
@@ -442,21 +442,27 @@
loadPages += 15
}
}}>
<div class="flex items-stretch mt-2 mb-2 w-full">
<div
class="{DBState.db.fixedChatTextarea ? 'sticky pt-2 pb-2 right-0 bottom-0 bg-bgcolor' : 'mt-2 mb-2'} flex items-stretch w-full"
style="{DBState.db.fixedChatTextarea ? 'z-index:29;' : ''}"
>
{#if DBState.db.useChatSticker && currentCharacter.type !== 'group'}
<div onclick={()=>{toggleStickers = !toggleStickers}}
class={"ml-4 bg-textcolor2 flex justify-center items-center w-12 h-12 rounded-md hover:bg-green-500 transition-colors "+(toggleStickers ? 'text-green-500':'text-textcolor')}>
<Laugh/>
</div>
class={"ml-4 bg-textcolor2 flex justify-center items-center w-12 h-12 rounded-md hover:bg-green-500 transition-colors "+(toggleStickers ? 'text-green-500':'text-textcolor')}>
<Laugh/>
</div>
{/if}
{#if !DBState.db.useAdvancedEditor}
<textarea class="peer text-input-area focus:border-textcolor transition-colors outline-none text-textcolor p-2 min-w-0 border border-r-0 bg-transparent rounded-md rounded-r-none input-text text-xl flex-grow ml-4 border-darkborderc resize-none overflow-y-hidden overflow-x-hidden max-w-full"
bind:value={messageInput}
bind:this={inputEle}
onkeydown={(e) => {
if(e.key.toLocaleLowerCase() === "enter" && (!e.shiftKey) && !e.isComposing){
if(DBState.db.sendWithEnter){
bind:value={messageInput}
bind:this={inputEle}
onkeydown={(e) => {
if(e.key.toLocaleLowerCase() === "enter" && !e.isComposing){
if(DBState.db.sendWithEnter && (!e.shiftKey)){
send()
e.preventDefault()
}else if(!DBState.db.sendWithEnter && e.shiftKey){
send()
e.preventDefault()
}
@@ -466,7 +472,7 @@
e.preventDefault()
}
}}
onpaste={(e) => {
onpaste={(e) => {
const items = e.clipboardData?.items
if(!items){
return
@@ -503,42 +509,42 @@
}
}
}}
oninput={()=>{updateInputSizeAll();updateInputTransateMessage(false)}}
style:height={inputHeight}
oninput={()=>{updateInputSizeAll();updateInputTransateMessage(false)}}
style:height={inputHeight}
></textarea>
{:else}
<AdvancedChatEditor
bind:value={messageInput}
bind:translate={messageInputTranslate}
/>
<AdvancedChatEditor
bind:value={messageInput}
bind:translate={messageInputTranslate}
/>
{/if}
{#if $doingChat || doingChatInputTranslate}
{#if $doingChat || doingChatInputTranslate}
<button
aria-labelledby="cancel"
class="peer-focus:border-textcolor flex justify-center border-y border-darkborderc items-center text-gray-100 p-3 hover:bg-blue-500 transition-colors" onclick={abortChat}
style:height={inputHeight}
aria-labelledby="cancel"
class="peer-focus:border-textcolor flex justify-center border-y border-darkborderc items-center text-gray-100 p-3 hover:bg-blue-500 transition-colors" onclick={abortChat}
style:height={inputHeight}
>
<div class="loadmove chat-process-stage-{$chatProcessStage}" class:autoload={autoMode}></div>
</button>
{:else}
<button
onclick={send}
class="flex justify-center border-y border-darkborderc items-center text-gray-100 p-3 peer-focus:border-textcolor hover:bg-blue-500 transition-colors button-icon-send"
style:height={inputHeight}
onclick={send}
class="flex justify-center border-y border-darkborderc items-center text-gray-100 p-3 peer-focus:border-textcolor hover:bg-blue-500 transition-colors button-icon-send"
style:height={inputHeight}
>
<Send />
</button>
{/if}
{#if DBState.db.characters[$selectedCharID]?.chaId !== '§playground'}
<button
onclick={(e) => {
onclick={(e) => {
openMenu = !openMenu
e.stopPropagation()
}}
class="peer-focus:border-textcolor mr-2 flex border-y border-r border-darkborderc justify-center items-center text-gray-100 p-3 rounded-r-md hover:bg-blue-500 transition-colors"
style:height={inputHeight}
class="peer-focus:border-textcolor mr-2 flex border-y border-r border-darkborderc justify-center items-center text-gray-100 p-3 rounded-r-md hover:bg-blue-500 transition-colors"
style:height={inputHeight}
>
<MenuIcon />
</button>
@@ -550,8 +556,8 @@
})
DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage] = DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage]
}}
class="peer-focus:border-textcolor mr-2 flex border-y border-r border-darkborderc justify-center items-center text-gray-100 p-3 rounded-r-md hover:bg-blue-500 transition-colors"
style:height={inputHeight}
class="peer-focus:border-textcolor mr-2 flex border-y border-r border-darkborderc justify-center items-center text-gray-100 p-3 rounded-r-md hover:bg-blue-500 transition-colors"
style:height={inputHeight}
>
<Plus />
</div>
@@ -563,9 +569,9 @@
<LanguagesIcon />
</label>
<textarea id = 'messageInputTranslate' class="text-textcolor rounded-md p-2 min-w-0 bg-transparent input-text text-xl flex-grow ml-4 mr-2 border-darkbutton resize-none focus:bg-selected overflow-y-hidden overflow-x-hidden max-w-full"
bind:value={messageInputTranslate}
bind:this={inputTranslateEle}
onkeydown={(e) => {
bind:value={messageInputTranslate}
bind:this={inputTranslateEle}
onkeydown={(e) => {
if(e.key.toLocaleLowerCase() === "enter" && (!e.shiftKey)){
if(DBState.db.sendWithEnter){
send()
@@ -577,10 +583,10 @@
e.preventDefault()
}
}}
oninput={()=>{updateInputSizeAll();updateInputTransateMessage(true)}}
placeholder={language.enterMessageForTranslateToEnglish}
style:height={inputTranslateHeight}
></textarea>
oninput={()=>{updateInputSizeAll();updateInputTransateMessage(true)}}
placeholder={language.enterMessageForTranslateToEnglish}
style:height={inputTranslateHeight}
></textarea>
</div>
{/if}
@@ -617,7 +623,7 @@
</div>
{/if}
{#if toggleStickers}
<div class="ml-4 flex flex-wrap">
<AssetInput bind:currentCharacter={currentCharacter} onSelect={(additionalAsset)=>{
@@ -632,7 +638,7 @@
messageInput += `<span class='notranslate' translate='no'>{{${fileType}::${additionalAsset[0]}}}</span> *${additionalAsset[0]} added*`
updateInputSizeAll()
}}/>
</div>
</div>
{/if}
{#if DBState.db.useAutoSuggestions}
@@ -642,13 +648,13 @@
: msg
)} {send}/>
{/if}
{#if DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].message?.[0]?.data?.startsWith(coldStorageHeader) }
{#await preLoadChat($selectedCharID, DBState.db.characters[$selectedCharID].chatPage)}
<div class="w-full flex justify-center text-textcolor2 italic mb-12">
{language.loadingChatData}
</div>
{:then a}
{:then a}
<div></div>
{/await}
{:else}
@@ -657,7 +663,7 @@
{#if DBState.db.characters[$selectedCharID].type !== 'group'}
<Chat
idx={chat.index}
name={DBState.db.characters[$selectedCharID].name}
name={DBState.db.characters[$selectedCharID].name}
message={chat.data}
img={getCharImage(DBState.db.characters[$selectedCharID].image, 'css')}
rerollIcon={i === 0}
@@ -671,7 +677,7 @@
{:else}
<Chat
idx={chat.index}
name={findCharacterbyId(chat.saying).name}
name={findCharacterbyId(chat.saying).name}
rerollIcon={i === 0}
message={chat.data}
onReroll={reroll}
@@ -687,7 +693,7 @@
<Chat
character={createSimpleCharacter(DBState.db.characters[$selectedCharID])}
idx={chat.index}
name={chat.name ?? currentUsername}
name={chat.name ?? currentUsername}
message={chat.data}
img={$ConnectionOpenStore ? '' : getCharImage(userIcon, 'css')}
isLastMemory={DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].lastMemory === (chat.chatId ?? 'none') && DBState.db.showMemoryLimit}
@@ -753,7 +759,7 @@
{/if}
{#if openMenu}
<div class="absolute right-2 bottom-16 p-5 bg-darkbg flex flex-col gap-3 text-textcolor rounded-md" onclick={(e) => {
<div class="{DBState.db.fixedChatTextarea ? 'fixed' : 'absolute'} right-2 bottom-16 p-5 bg-darkbg flex flex-col gap-3 text-textcolor rounded-md" onclick={(e) => {
e.stopPropagation()
}}>
{#if DBState.db.characters[$selectedCharID].type === 'group'}

View File

@@ -1,7 +1,6 @@
<script lang="ts">
import Check from "src/lib/UI/GUI/CheckInput.svelte";
import { language } from "src/lang";
import { DBState } from 'src/ts/stores.svelte';
</script>
@@ -24,6 +23,10 @@
<Check bind:check={DBState.db.sendWithEnter} name={language.sendWithEnter}/>
</div>
<div class="flex items-center mt-2">
<Check bind:check={DBState.db.fixedChatTextarea} name={language.fixedChatTextarea}/>
</div>
<div class="flex items-center mt-2">
<Check bind:check={DBState.db.clickToEdit} name={language.clickToEdit}/>
</div>

View File

@@ -56,7 +56,7 @@
<button class={(DBState.db.enabledModules.includes(rmodule.id)) ?
"mr-2 cursor-pointer text-blue-500" :
rmodule.namespace &&
DBState.db.moduleIntergration.split(',').map((s) => s.trim()).includes(rmodule.namespace) ?
DBState.db.moduleIntergration?.split(',').map((s) => s.trim()).includes(rmodule.namespace) ?
"text-amber-500 hover:text-green-500 mr-2 cursor-pointer" :
"text-textcolor2 hover:text-green-500 mr-2 cursor-pointer"
} use:tooltip={language.enableGlobal} onclick={async (e) => {

View File

@@ -1278,7 +1278,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
}
case 'getglobalvar':{
return getGlobalChatVar(v)
}
} // setglobalvar cbs support?
case 'button':{
return `<button class="button-default" risu-trigger="${arra[2]}">${arra[1]}</button>`
}
@@ -1379,7 +1379,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
case 'previous_chat_log':{
const selchar = db.characters[get(selectedCharID)]
const chat = selchar?.chats?.[selchar.chatPage]
return chat?.message[chatID - 1]?.data ?? 'Out of range'
return chat?.message[Number(arra[1])]?.data ?? 'Out of range'
}
case 'tonumber':{
@@ -2235,6 +2235,10 @@ export function getGlobalChatVar(key:string){
return DBState.db.globalChatVariables[key] ?? 'null'
}
export function setGlobalChatVar(key:string, value:string){
DBState.db.globalChatVariables[key] = value // String to String Map(dictionary)
}
export function setChatVar(key:string, value:string){
const selectedChar = get(selectedCharID)
if(!DBState.db.characters[selectedChar].chats[DBState.db.characters[selectedChar].chatPage].scriptstate){

View File

@@ -1,4 +1,4 @@
import { getChatVar, hasher, setChatVar, type simpleCharacterArgument } from "../parser.svelte";
import { getChatVar, hasher, setChatVar, getGlobalChatVar, type simpleCharacterArgument } from "../parser.svelte";
import { LuaEngine, LuaFactory } from "wasmoon";
import { getCurrentCharacter, getCurrentChat, getDatabase, setCurrentChat, setDatabase, type Chat, type character, type groupChat } from "../storage/database.svelte";
import { get } from "svelte/store";
@@ -25,7 +25,8 @@ interface LuaEngineState {
mutex: Mutex;
chat: Chat;
setVar: (key:string, value:string) => void,
getVar: (key:string) => string
getVar: (key:string) => string,
getGlobalVar: (key:string) => any,
}
let LuaEngines = new Map<string, LuaEngineState>()
@@ -35,6 +36,7 @@ export async function runLua(code:string, arg:{
chat?:Chat
setVar?: (key:string, value:string) => void,
getVar?: (key:string) => string,
getGlobalVar?: (key:string) => any,
lowLevelAccess?: boolean,
mode?: string,
data?: any
@@ -42,6 +44,7 @@ export async function runLua(code:string, arg:{
const char = arg.char ?? getCurrentCharacter()
const setVar = arg.setVar ?? setChatVar
const getVar = arg.getVar ?? getChatVar
const getGlobalVar = arg.getGlobalVar ?? getGlobalChatVar
const mode = arg.mode ?? 'manual'
const data = arg.data ?? {}
let chat = arg.chat ?? getCurrentChat()
@@ -60,7 +63,8 @@ export async function runLua(code:string, arg:{
mutex: new Mutex(),
chat,
setVar,
getVar
getVar,
getGlobalVar
}
LuaEngines.set(mode, luaEngineState)
wasEmpty = true
@@ -68,6 +72,7 @@ export async function runLua(code:string, arg:{
luaEngineState.chat = chat
luaEngineState.setVar = setVar
luaEngineState.getVar = getVar
luaEngineState.getGlobalVar = getGlobalVar
}
return await luaEngineState.mutex.runExclusive(async () => {
if (wasEmpty || code !== luaEngineState.code) {
@@ -87,6 +92,12 @@ export async function runLua(code:string, arg:{
}
return luaEngineState.getVar(key)
})
luaEngine.global.set('getGlobalVar', (id:string, key:string) => {
if(!LuaSafeIds.has(id) && !LuaEditDisplayIds.has(id)){
return
}
return luaEngineState.getGlobalVar(key)
})
luaEngine.global.set('stopChat', (id:string) => {
if(!LuaSafeIds.has(id)){
return

View File

@@ -694,6 +694,7 @@ export interface Database{
}
globalscript: customscript[],
sendWithEnter:boolean
fixedChatTextarea:boolean
clickToEdit: boolean
koboldURL:string
advancedBotSettings:boolean