diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 8b4e30ae..910f4cda 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -29,7 +29,7 @@
},
"productName": "RisuAI",
"mainBinaryName": "RisuAI",
- "version": "140.1.0",
+ "version": "141.0.0",
"identifier": "co.aiclient.risu",
"plugins": {
"updater": {
diff --git a/src/lib/ChatScreens/Chat.svelte b/src/lib/ChatScreens/Chat.svelte
index 1f5995d1..bb646480 100644
--- a/src/lib/ChatScreens/Chat.svelte
+++ b/src/lib/ChatScreens/Chat.svelte
@@ -2,7 +2,7 @@
import { ArrowLeft, Sparkles, ArrowRight, PencilIcon, LanguagesIcon, RefreshCcwIcon, TrashIcon, CopyIcon, Volume2Icon, BotIcon, ArrowLeftRightIcon, UserIcon } from "lucide-svelte";
import { type CbsConditions, ParseMarkdown, postTranslationParse, type simpleCharacterArgument } from "../../ts/parser.svelte";
import AutoresizeArea from "../UI/GUI/TextAreaResizable.svelte";
- import { alertConfirm, alertError, alertNormal, alertRequestData, alertWait } from "../../ts/alert";
+ import { alertClear, alertConfirm, alertError, alertNormal, alertRequestData, alertWait } from "../../ts/alert";
import { language } from "../../lang";
import { type MessageGenerationInfo } from "../../ts/storage/database.svelte";
import { alertStore, DBState } from 'src/ts/stores.svelte';
@@ -140,11 +140,12 @@
translateText = false
try {
if(DBState.db.autoTranslate){
- if(DBState.db.autoTranslateCachedOnly && DBState.db.translatorType === "llm"){
- const cache = await getLLMCache(data)
- if(cache !== null){
- translateText = true
- }
+ if(DBState.db.autoTranslateCachedOnly && DBState.db.translatorType === 'llm'){
+ const cache = DBState.db.translateBeforeHTMLFormatting
+ ? await getLLMCache(data)
+ : await getLLMCache(await ParseMarkdown(data, charArg, 'pretranslate', chatID, getCbsCondition()))
+
+ translateText = cache !== null
}
else{
translateText = true
@@ -430,7 +431,10 @@
return
}
catch (e) {
- alertError(`Error, please try again: ${e.message}`)
+ alertClear()
+ window.navigator.clipboard.writeText(msgDisplay).then(() => {
+ setStatusMessage(language.copied)
+ })
}
}
window.navigator.clipboard.writeText(msgDisplay).then(() => {
diff --git a/src/lib/UI/PromptDataItem.svelte b/src/lib/UI/PromptDataItem.svelte
index 2a270abb..c1b2656d 100644
--- a/src/lib/UI/PromptDataItem.svelte
+++ b/src/lib/UI/PromptDataItem.svelte
@@ -10,6 +10,7 @@
import TextInput from "./GUI/TextInput.svelte";
import { DBState } from 'src/ts/stores.svelte';
+ let opened = $state(false)
interface Props {
promptItem: PromptItem;
onRemove?: () => void;
@@ -36,101 +37,224 @@
promptItem = currentprompt
}
-
+ function getName(promptItem:PromptItem){
-
-
-
-
-
-
-
{language.type}
-
-
{
- if(promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'){
- promptItem.text = ""
- promptItem.role = "system"
+ if(promptItem.name){
+ return promptItem.name
+ }
+
+ if(promptItem.type === 'plain'){
+ return language.formating.plain
+ }
+ if(promptItem.type === 'jailbreak'){
+ return language.formating.jailbreak
}
if(promptItem.type === 'chat'){
- promptItem.rangeStart = -1000
- promptItem.rangeEnd = 'end'
+ return language.Chat
}
- }} >
- {language.formating.plain}
- {language.formating.jailbreak}
- {language.Chat}
- {language.formating.personaPrompt}
- {language.formating.description}
- {language.formating.authorNote}
- {language.formating.lorebook}
- {language.formating.memory}
- {language.formating.postEverything}
- {#if DBState.db.promptSettings.customChainOfThought}
- {language.cot}
- {/if}
-
+ if(promptItem.type === 'persona'){
+ return language.formating.personaPrompt
+ }
+ if(promptItem.type === 'description'){
+ return language.formating.description
+ }
+ if(promptItem.type === 'authornote'){
+ return language.formating.authorNote
+ }
+ if(promptItem.type === 'lorebook'){
+ return language.formating.lorebook
+ }
+ if(promptItem.type === 'memory'){
+ return language.formating.memory
+ }
+ if(promptItem.type === 'postEverything'){
+ return language.formating.postEverything
+ }
+ if(promptItem.type === 'cot'){
+ return language.cot
+ }
+ if(promptItem.type === 'chatML'){
+ return 'ChatML'
+ }
+ return ""
+ }
- {#if promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'}
-
{language.specialType}
-
- {language.noSpecialType}
- {language.mainPrompt}
- {language.globalNote}
+ function replacePrompt(prompt:PromptItem){
+ if(JSON.stringify(promptItem) === JSON.stringify(prompt)){
+ return
+ }
+
+ const ind = DBState.db.promptTemplate.findIndex((item, index) => {
+ return JSON.stringify(item) === JSON.stringify(prompt)
+ })
+
+ if(ind !== -1){
+ DBState.db.promptTemplate.splice(ind, 1)
+ }
+ const myInd = DBState.db.promptTemplate.findIndex((item, index) => {
+ return JSON.stringify(item) === JSON.stringify(promptItem)
+ })
+ DBState.db.promptTemplate.splice(myInd, 0, prompt)
+
+ }
+
+
+
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ const data = e.dataTransfer.getData('text')
+ if(data === 'prompt'){
+ const prompt = JSON.parse(e.dataTransfer.getData('prompt'))
+ replacePrompt(prompt)
+ }
+}} ondragover={(e) => {
+ e.preventDefault()
+}} draggable="true" ondragstart={(e) => {
+ e.dataTransfer.setData('text', 'prompt')
+ e.dataTransfer.setData('prompt', JSON.stringify(promptItem))
+}}>
+
+
+
+ {
+ e.preventDefault()
+ }}
+ ondrop={(e) => {
+ e.preventDefault()
+ const data = e.dataTransfer.getData('text')
+ if(data === 'prompt'){
+ const prompt = JSON.parse(e.dataTransfer.getData('prompt'))
+ replacePrompt(prompt)
+ }
+ }}
+ draggable={opened ? false : true}
+ ondragstart={(e) => {
+ e.dataTransfer.setData('text', 'prompt')
+ e.dataTransfer.setData('prompt', JSON.stringify(promptItem))
+ }}
+>
+
+
{
+ opened = !opened
+ }}>
+
{getName(promptItem)}
+
+
+
+
+
+
+ {#if opened}
+
+
+
{language.name}
+
+
{language.type}
+
{
+ if(promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'){
+ promptItem.text = ""
+ promptItem.role = "system"
+ }
+ if(promptItem.type === 'chat'){
+ promptItem.rangeStart = -1000
+ promptItem.rangeEnd = 'end'
+ }
+ }} >
+ {language.formating.plain}
+ {language.formating.jailbreak}
+ {language.Chat}
+ {language.formating.personaPrompt}
+ {language.formating.description}
+ {language.formating.authorNote}
+ {language.formating.lorebook}
+ {language.formating.memory}
+ {language.formating.postEverything}
+ {"chatML"}
+
+ {#if DBState.db.promptSettings.customChainOfThought}
+ {language.cot}
+ {/if}
-
{language.prompt}
-
-
{language.role}
-
- {language.user}
- {language.character}
- {language.systemPrompt}
-
- {/if}
- {#if promptItem.type === 'chat'}
- {#if promptItem.rangeStart !== -1000}
-
{language.rangeStart}
-
-
{language.rangeEnd}
- {#if promptItem.rangeEnd === 'end'}
-
-
{
- if(promptItem.type === 'chat'){
- promptItem.rangeEnd = 0
+
+ {#if promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'}
+ {language.specialType}
+
+ {language.noSpecialType}
+ {language.mainPrompt}
+ {language.globalNote}
+
+ {language.prompt}
+
+ {language.role}
+
+ {language.user}
+ {language.character}
+ {language.systemPrompt}
+
+ {/if}
+ {#if promptItem.type === 'chatML'}
+ {language.prompt}
+
+ {/if}
+ {#if promptItem.type === 'chat'}
+ {#if promptItem.rangeStart !== -1000}
+ {language.rangeStart}
+
+ {language.rangeEnd}
+ {#if promptItem.rangeEnd === 'end'}
+
+ {
+ if(promptItem.type === 'chat'){
+ promptItem.rangeEnd = 0
+ }
+ }} />
+ {:else}
+
+ {
+ if(promptItem.type === 'chat'){
+ promptItem.rangeEnd = 'end'
+ }
+ }} />
+ {/if}
+ {#if DBState.db.promptSettings.sendChatAsSystem}
+
+ {/if}
+ {/if}
+
+ {/if}
+ {#if promptItem.type === 'authornote'}
+ {language.defaultPrompt}
+
+ {/if}
+ {#if promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'}
+ {#if !promptItem.innerFormat}
+ {
+ if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
+ promptItem.innerFormat = "{{slot}}"
}
}} />
{:else}
-
- {
- if(promptItem.type === 'chat'){
- promptItem.rangeEnd = 'end'
+ {language.innerFormat}
+
+ {
+ if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
+ promptItem.innerFormat = null
}
}} />
{/if}
- {#if DBState.db.promptSettings.sendChatAsSystem}
-
- {/if}
- {/if}
-
- {/if}
- {#if promptItem.type === 'authornote'}
- {language.defaultPrompt}
-
- {/if}
- {#if promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'}
- {#if !promptItem.innerFormat}
- {
- if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
- promptItem.innerFormat = "{{slot}}"
- }
- }} />
- {:else}
- {language.innerFormat}
-
- {
- if(promptItem.type === 'persona' || promptItem.type === 'description' || promptItem.type === 'authornote' || promptItem.type === 'memory'){
- promptItem.innerFormat = null
- }
- }} />
{/if}
{/if}
\ No newline at end of file
diff --git a/src/ts/parser.svelte.ts b/src/ts/parser.svelte.ts
index 82ec755e..71dbe1f3 100644
--- a/src/ts/parser.svelte.ts
+++ b/src/ts/parser.svelte.ts
@@ -411,7 +411,7 @@ export async function ParseMarkdown(
if(firstParsed !== data && char && char.type !== 'group'){
data = await parseAdditionalAssets(data, char, additionalAssetMode, 'post')
}
- data = await parseInlayImages(data)
+ data = await parseInlayImages(data ?? '')
data = encodeStyle(data)
if(mode === 'normal'){
@@ -720,7 +720,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){
return ""
}
- return achara.personality
+ return risuChatParser(achara.personality, matcherArg)
}
case 'description':
case 'char_desc':{
@@ -729,7 +729,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){
return ""
}
- return achara.desc
+ return risuChatParser(achara.desc, matcherArg)
}
case 'scenario':{
const argChara = chara
@@ -737,7 +737,7 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){
return ""
}
- return achara.scenario
+ return risuChatParser(achara.scenario, matcherArg)
}
case 'example_dialogue':
case 'example_message':{
@@ -746,15 +746,15 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(achara.type === 'group'){
return ""
}
- return achara.exampleMessage
+ return risuChatParser(achara.exampleMessage, matcherArg)
}
case 'persona':
case 'user_persona':{
- return getPersonaPrompt()
+ return risuChatParser(getPersonaPrompt(), matcherArg)
}
case 'main_prompt':
case 'system_prompt':{
- return db.mainPrompt
+ return risuChatParser(db.mainPrompt, matcherArg)
}
case 'lorebook':
case 'world_info':{
@@ -765,49 +765,56 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
const characterLore = (achara.type === 'group') ? [] : (achara.globalLore ?? [])
const chatLore = chat.localLore ?? []
const fullLore = characterLore.concat(chatLore.concat(getModuleLorebooks()))
- return fullLore.map((f) => {
- return JSON.stringify(f)
- }).join("§\n")
+ return makeArray(fullLore.map((v) => {
+ return JSON.stringify(v)
+ }))
}
case 'history':
case 'messages':{
const selchar = db.characters[get(selectedCharID)]
const chat = selchar.chats[selchar.chatPage]
- return chat.message.map((f) => {
- return f.role + ': ' + f.data
- }).join("§\n")
+ return makeArray([{
+ role: 'char',
+ data: chat.fmIndex === -1 ? selchar.firstMessage : selchar.alternateGreetings[chat.fmIndex]
+ }].concat(chat.message).map((v) => {
+ v = safeStructuredClone(v)
+ v.data = risuChatParser(v.data, matcherArg)
+ return JSON.stringify(v)
+ }))
}
case 'user_history':
case 'user_messages':{
const selchar = db.characters[get(selectedCharID)]
const chat = selchar.chats[selchar.chatPage]
- return chat.message.map((f) => {
- if(f.role === 'user'){
- return f.data
- }
- return ''
- }).filter((f) => {
- return f !== ''
- }).join("§\n")
+ return makeArray(chat.message.filter((v) => {
+ return v.role === 'user'
+ }).map((v) => {
+ v = safeStructuredClone(v)
+ v.data = risuChatParser(v.data, matcherArg)
+ return JSON.stringify(v)
+ }))
}
case 'char_history':
case 'char_messages':{
const selchar = db.characters[get(selectedCharID)]
const chat = selchar.chats[selchar.chatPage]
- return chat.message.map((f) => {
- if(f.role === 'char'){
- return f.data
- }
- return ''
- }).filter((f) => {
- return f !== ''
- }).join("§\n")
+ return makeArray(chat.message.filter((v) => {
+ return v.role === 'char'
+ }).map((v) => {
+ v = safeStructuredClone(v)
+ v.data = risuChatParser(v.data, matcherArg)
+ return JSON.stringify(v)
+ }))
+ }
+ case 'jb':
+ case 'jailbreak':{
+ return risuChatParser(db.jailbreak, matcherArg)
}
case 'ujb':
case 'global_note':
case 'system_note':{
- return db.globalNote
+ return risuChatParser(db.globalNote, matcherArg)
}
case 'chat_index':{
return chatID.toString()
@@ -1038,9 +1045,9 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
if(!selchar || selchar.type === 'group'){
return ''
}
- return selchar.additionalAssets?.map((f) => {
+ return makeArray(selchar.additionalAssets?.map((f) => {
return f[0]
- })?.join('§') ?? ''
+ }))
}
case 'prefill_supported':{
return db.aiModel.startsWith('claude') ? '1' : '0'
@@ -1286,7 +1293,9 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
}
case 'arraypush':
case 'array_push':{
- return arra[1] + '§' + arra[2]
+ const arr = parseArray(arra[1])
+ arr.push(arra[2])
+ return makeArray(arr)
}
case 'arraysplice':
case 'array_splice':{
@@ -1351,14 +1360,13 @@ function basicMatcher (p1:string,matcherArg:matcherArg,vars:{[key:string]:string
const start = arr.length > 1 ? Number(arr[0]) : 0
const end = arr.length > 1 ? Number(arr[1]) : Number(arr[0])
const step = arr.length > 2 ? Number(arr[2]) : 1
- let out = ''
+ let out:string[] = []
+
for(let i=start;i = arg.functions ?? (new Map())
+ arg.callStack = (arg.callStack ?? 0) + 1
+
+ if(arg.callStack > 20){
+ return 'ERROR: Call stack limit reached'
+ }
+
const matcherObj = {
chatID: chatID,
chara: chara,
@@ -1842,7 +1860,8 @@ export function risuChatParser(da:string, arg:{
role: arg.role,
runVar: arg.runVar ?? false,
consistantChar: arg.consistantChar ?? false,
- cbsConditions: arg.cbsConditions ?? {}
+ cbsConditions: arg.cbsConditions ?? {},
+ callStack: arg.callStack,
}
@@ -1971,7 +1990,7 @@ export function risuChatParser(da:string, arg:{
}
}
if(dat.startsWith('call::')){
- if(arg.callStack && arg.callStack > 10){
+ if(arg.callStack && arg.callStack > 20){
nested[0] += `ERROR: Call stack limit reached`
break
}
@@ -1985,7 +2004,6 @@ export function risuChatParser(da:string, arg:{
data = data.replaceAll(`{{arg::${i}}}`, argData[i])
}
arg.functions = functions
- arg.callStack = (arg.callStack ?? 0) + 1
nested[0] += risuChatParser(data, arg)
break
}
@@ -2280,7 +2298,7 @@ export function parseChatML(data:string):OpenAIChat[]|null{
return {
role: role,
- content: v
+ content: risuChatParser(v)
}
})
}
diff --git a/src/ts/process/index.svelte.ts b/src/ts/process/index.svelte.ts
index 47dcfd44..b6f73e64 100644
--- a/src/ts/process/index.svelte.ts
+++ b/src/ts/process/index.svelte.ts
@@ -28,6 +28,7 @@ import { runImageEmbedding } from "./transformers";
import { hanuraiMemory } from "./memory/hanuraiMemory";
import { hypaMemoryV2 } from "./memory/hypav2";
import { runLuaEditTrigger } from "./lua";
+import { parseChatML } from "../parser.svelte";
export interface OpenAIChat{
role: 'system'|'user'|'assistant'|'function'
@@ -548,6 +549,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{
await tokenizeChatArray([prompt])
break
}
+ case 'chatML':{
+ let prompts = parseChatML(card.text)
+ await tokenizeChatArray(prompts)
+ break
+ }
case 'chat':{
let start = card.rangeStart
let end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd
@@ -1007,6 +1013,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{
pushPrompts([prompt])
break
}
+ case 'chatML':{
+ let prompts = parseChatML(card.text)
+ pushPrompts(prompts)
+ break
+ }
case 'chat':{
let start = card.rangeStart
let end = (card.rangeEnd === 'end') ? unformated.chats.length : card.rangeEnd
diff --git a/src/ts/process/prompt.ts b/src/ts/process/prompt.ts
index a5e764f1..89c49dd2 100644
--- a/src/ts/process/prompt.ts
+++ b/src/ts/process/prompt.ts
@@ -4,7 +4,7 @@ import { getDatabase, presetTemplate, setDatabase, type Database } from "../stor
import { alertError, alertNormal } from "../alert";
import type { OobaChatCompletionRequestParams } from "../model/ooba";
-export type PromptItem = PromptItemPlain|PromptItemTyped|PromptItemChat|PromptItemAuthorNote;
+export type PromptItem = PromptItemPlain|PromptItemTyped|PromptItemChat|PromptItemAuthorNote|PromptItemChatML
export type PromptType = PromptItem['type'];
export type PromptSettings = {
assistantPrefill: string
@@ -21,17 +21,26 @@ export interface PromptItemPlain {
type2: 'normal'|'globalNote'|'main'
text: string;
role: 'user'|'bot'|'system';
+ name?: string
+}
+
+export interface PromptItemChatML {
+ type: 'chatML'
+ text: string
+ name?: string
}
export interface PromptItemTyped {
type: 'persona'|'description'|'lorebook'|'postEverything'|'memory'
- innerFormat?: string
+ innerFormat?: string,
+ name?: string
}
export interface PromptItemAuthorNote {
type : 'authornote'
innerFormat?: string
defaultText?: string
+ name?: string
}
@@ -40,6 +49,7 @@ export interface PromptItemChat {
rangeStart: number;
rangeEnd: number|'end';
chatAsOriginalOnSystem?: boolean;
+ name?: string
}
export async function tokenizePreset(prompts:PromptItem[], consti:boolean = false){
diff --git a/src/ts/storage/database.svelte.ts b/src/ts/storage/database.svelte.ts
index 734149e8..5fdb1db0 100644
--- a/src/ts/storage/database.svelte.ts
+++ b/src/ts/storage/database.svelte.ts
@@ -12,7 +12,7 @@ import { defaultColorScheme, type ColorScheme } from '../gui/colorscheme';
import type { PromptItem, PromptSettings } from '../process/prompt';
import type { OobaChatCompletionRequestParams } from '../model/ooba';
-export let appVer = "140.1.0"
+export let appVer = "141.0.0"
export let webAppSubVer = ''
diff --git a/src/ts/translator/translator.ts b/src/ts/translator/translator.ts
index 156db65d..b8ce3041 100644
--- a/src/ts/translator/translator.ts
+++ b/src/ts/translator/translator.ts
@@ -111,7 +111,7 @@ export async function runTranslator(text:string, reverse:boolean, from:string,ta
async function translateMain(text:string, arg:{from:string, to:string, host:string}){
let db = getDatabase()
if(db.translatorType === 'llm'){
- const tr = db.translator || 'en'
+ const tr = arg.to || 'en'
return translateLLM(text, {to: tr})
}
if(db.translatorType === 'deepl'){
diff --git a/version.json b/version.json
index 410941cf..9e7a354d 100644
--- a/version.json
+++ b/version.json
@@ -1 +1 @@
-{"version":"140.1.0"}
\ No newline at end of file
+{"version":"141.0.0"}
\ No newline at end of file