Merge branch 'kwaroran:main' into main

This commit is contained in:
bangonicdd2
2024-02-08 00:29:24 +09:00
committed by GitHub
13 changed files with 165 additions and 110 deletions

View File

@@ -8,7 +8,7 @@
}, },
"package": { "package": {
"productName": "RisuAI", "productName": "RisuAI",
"version": "1.77.0" "version": "1.78.2"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {

View File

@@ -1,13 +1,19 @@
export const patchNote = { export const patchNote = {
version: "1.77", version: "1.78",
content: content:
` `
# Update 1.77 # Update 1.78
- Added Risu RCC export - Added Modules
- Added password protection - Modules are package of triggers, regex, and lorebook
- Added license for file export - You can enable globally, or enable only in specific chat
- Added memory limit border thickness (#286) - Designed for easy sharing and activation/deactivation.
- Minor fixes - Removed global regex and lorebook
- This would be replaced by modules
- Old global regex and lorebook will be converted to modules
- Fixed Claude prompting
- Settings menu would be remembered
- Added persona portraits (#289)
- Added gpt-3.5-turbo-0125 (#288)
` `
} }

View File

@@ -529,4 +529,5 @@ export const languageEnglish = {
edit: "Edit", edit: "Edit",
enableGlobal: "Enable Globally", enableGlobal: "Enable Globally",
chatModulesInfo: "You can enable or disable modules for this chat.", chatModulesInfo: "You can enable or disable modules for this chat.",
sideMenuRerollButton: "Side Menu Reroll Button",
} }

View File

@@ -675,6 +675,13 @@
<PackageIcon /> <PackageIcon />
<span class="ml-2">{language.modules}</span> <span class="ml-2">{language.modules}</span>
</div> </div>
{#if $DataBase.sideMenuRerollButton}
<div class="flex items-center cursor-pointer hover:text-green-500 transition-colors" on:click={reroll}>
<RefreshCcwIcon />
<span class="ml-2">{language.reroll}</span>
</div>
{/if}
</div> </div>
{/if} {/if}

View File

@@ -37,4 +37,8 @@
<div class="flex items-center mt-2"> <div class="flex items-center mt-2">
<Check bind:check={$DataBase.showMenuChatList} name={language.showMenuChatList}/> <Check bind:check={$DataBase.showMenuChatList} name={language.showMenuChatList}/>
</div>
<div class="flex items-center mt-2">
<Check bind:check={$DataBase.sideMenuRerollButton} name={language.sideMenuRerollButton}/>
</div> </div>

View File

@@ -3,7 +3,7 @@
import { DataBase } from "src/ts/storage/database"; import { DataBase } from "src/ts/storage/database";
import Button from "src/lib/UI/GUI/Button.svelte"; import Button from "src/lib/UI/GUI/Button.svelte";
import ModuleMenu from "src/lib/Setting/Pages/Module/ModuleMenu.svelte"; import ModuleMenu from "src/lib/Setting/Pages/Module/ModuleMenu.svelte";
import { exportModule, type RisuModule } from "src/ts/process/modules"; import { exportModule, importModule, type RisuModule } from "src/ts/process/modules";
import { DownloadIcon, Edit, TrashIcon, Globe } from "lucide-svelte"; import { DownloadIcon, Edit, TrashIcon, Globe } from "lucide-svelte";
import { v4 } from "uuid"; import { v4 } from "uuid";
import { tooltip } from "src/ts/gui/tooltip"; import { tooltip } from "src/ts/gui/tooltip";
@@ -87,7 +87,7 @@
} }
mode = 1 mode = 1
}}>{language.createModule}</Button> }}>{language.createModule}</Button>
<Button className="mt-2">{language.importModule}</Button> <Button className="mt-2" on:click={importModule}>{language.importModule}</Button>
{:else if mode === 1} {:else if mode === 1}
<h2 class="mb-2 text-2xl font-bold mt-2">{language.createModule}</h2> <h2 class="mb-2 text-2xl font-bold mt-2">{language.createModule}</h2>
<ModuleMenu bind:currentModule={tempModule}/> <ModuleMenu bind:currentModule={tempModule}/>
@@ -95,7 +95,7 @@
<Button className="mt-6" on:click={() => { <Button className="mt-6" on:click={() => {
$DataBase.modules.push(tempModule) $DataBase.modules.push(tempModule)
mode = 0 mode = 0
}}>{language.editModule}</Button> }}>{language.createModule}</Button>
{/if} {/if}
{:else if mode === 2} {:else if mode === 2}
<h2 class="mb-2 text-2xl font-bold mt-2">{language.editModule}</h2> <h2 class="mb-2 text-2xl font-bold mt-2">{language.editModule}</h2>
@@ -104,6 +104,6 @@
<Button className="mt-6" on:click={() => { <Button className="mt-6" on:click={() => {
$DataBase.modules[editModuleIndex] = tempModule $DataBase.modules[editModuleIndex] = tempModule
mode = 0 mode = 0
}}>{language.createModule}</Button> }}>{language.editModule}</Button>
{/if} {/if}
{/if} {/if}

View File

@@ -88,24 +88,6 @@
<AccessibilityIcon /> <AccessibilityIcon />
<span>{language.accessibility}</span> <span>{language.accessibility}</span>
</button> </button>
<button class="flex gap-2 items-center hover:text-textcolor"
class:text-textcolor={$SettingsMenuIndex === 8}
class:text-textcolor2={$SettingsMenuIndex !== 8}
on:click={() => {
$SettingsMenuIndex = 8
}}>
<BookIcon />
<span>{language.globalLoreBook}</span>
</button>
<button class="flex gap-2 items-center hover:text-textcolor"
class:text-textcolor={$SettingsMenuIndex === 9}
class:text-textcolor2={$SettingsMenuIndex !== 9}
on:click={() => {
$SettingsMenuIndex = 9
}}>
<AlignLeft />
<span>{language.globalRegexScript}</span>
</button>
<button class="flex gap-2 items-center hover:text-textcolor" <button class="flex gap-2 items-center hover:text-textcolor"
class:text-textcolor={$SettingsMenuIndex === 14} class:text-textcolor={$SettingsMenuIndex === 14}
class:text-textcolor2={$SettingsMenuIndex !== 14} class:text-textcolor2={$SettingsMenuIndex !== 14}

View File

@@ -12,6 +12,7 @@ import { calcString } from './process/infunctions';
import { findCharacterbyId } from './util'; import { findCharacterbyId } from './util';
import { getInlayImage } from './image'; import { getInlayImage } from './image';
import { autoMarkNew } from './plugins/automark'; import { autoMarkNew } from './plugins/automark';
import { getModuleLorebooks } from './process/modules';
const mconverted = new Marked({ const mconverted = new Marked({
gfm: true, gfm: true,
@@ -490,8 +491,7 @@ const matcher = (p1:string,matcherArg:matcherArg) => {
const chat = selchar.chats[selchar.chatPage] const chat = selchar.chats[selchar.chatPage]
const characterLore = (achara.type === 'group') ? [] : (achara.globalLore ?? []) const characterLore = (achara.type === 'group') ? [] : (achara.globalLore ?? [])
const chatLore = chat.localLore ?? [] const chatLore = chat.localLore ?? []
const globalLore = db.loreBook[db.loreBookPage]?.data ?? [] const fullLore = characterLore.concat(chatLore.concat(getModuleLorebooks()))
const fullLore = characterLore.concat(chatLore.concat(globalLore))
return fullLore.map((f) => { return fullLore.map((f) => {
return JSON.stringify(f) return JSON.stringify(f)
}).join("§\n") }).join("§\n")

View File

@@ -12,19 +12,7 @@ import { getModuleLorebooks } from "./modules";
export function addLorebook(type:number) { export function addLorebook(type:number) {
let selectedID = get(selectedCharID) let selectedID = get(selectedCharID)
let db = get(DataBase) let db = get(DataBase)
if(type === -1){ if(type === 0){
db.loreBook[db.loreBookPage].data.push({
key: '',
comment: `New Lore ${db.loreBook[db.loreBookPage].data.length + 1}`,
content: '',
mode: 'normal',
insertorder: 100,
alwaysActive: false,
secondkey: "",
selective: false
})
}
else if(type === 0){
db.characters[selectedID].globalLore.push({ db.characters[selectedID].globalLore.push({
key: '', key: '',
comment: `New Lore ${db.characters[selectedID].globalLore.length + 1}`, comment: `New Lore ${db.characters[selectedID].globalLore.length + 1}`,
@@ -71,9 +59,8 @@ export async function loadLoreBookPrompt(){
const page = char.chatPage const page = char.chatPage
const characterLore = char.globalLore ?? [] const characterLore = char.globalLore ?? []
const chatLore = char.chats[page].localLore ?? [] const chatLore = char.chats[page].localLore ?? []
const globalLore = db.loreBook[db.loreBookPage]?.data ?? []
const moduleLorebook = getModuleLorebooks() const moduleLorebook = getModuleLorebooks()
const fullLore = characterLore.concat(chatLore).concat(moduleLorebook).concat(globalLore) const fullLore = characterLore.concat(chatLore).concat(moduleLorebook)
const currentChat = char.chats[page].message const currentChat = char.chats[page].message
const loreDepth = char.loreSettings?.scanDepth ?? db.loreBookDepth const loreDepth = char.loreSettings?.scanDepth ?? db.loreBookDepth
const loreToken = char.loreSettings?.tokenBudget ?? db.loreBookToken const loreToken = char.loreSettings?.tokenBudget ?? db.loreBookToken
@@ -224,8 +211,7 @@ export async function loadLoreBookPlusPrompt(){
const page = char.chatPage const page = char.chatPage
const characterLore = char.globalLore ?? [] const characterLore = char.globalLore ?? []
const chatLore = char.chats[page].localLore ?? [] const chatLore = char.chats[page].localLore ?? []
const globalLore = db.loreBook[db.loreBookPage]?.data ?? [] const fullLore = characterLore.concat(chatLore).concat(getModuleLorebooks()).filter((v) => { return v.content })
const fullLore = characterLore.concat(chatLore.concat(globalLore)).filter((v) => { return v.content })
const currentChat = char.chats[page].message const currentChat = char.chats[page].message
const loreDepth = char.loreSettings?.scanDepth ?? db.loreBookDepth const loreDepth = char.loreSettings?.scanDepth ?? db.loreBookDepth
const loreToken = char.loreSettings?.tokenBudget ?? db.loreBookToken const loreToken = char.loreSettings?.tokenBudget ?? db.loreBookToken
@@ -317,7 +303,6 @@ export async function importLoreBook(mode:'global'|'local'|'sglobal'){
const page = mode === 'sglobal' ? -1 : db.characters[selectedID].chatPage const page = mode === 'sglobal' ? -1 : db.characters[selectedID].chatPage
let lore = let lore =
mode === 'global' ? db.characters[selectedID].globalLore : mode === 'global' ? db.characters[selectedID].globalLore :
mode === 'sglobal' ? db.loreBook[db.loreBookPage].data :
db.characters[selectedID].chats[page].localLore db.characters[selectedID].chats[page].localLore
const lorebook = (await selectSingleFile(['json', 'lorebook'])).data const lorebook = (await selectSingleFile(['json', 'lorebook'])).data
if(!lorebook){ if(!lorebook){
@@ -335,50 +320,12 @@ export async function importLoreBook(mode:'global'|'local'|'sglobal'){
} }
} }
else if(importedlore.entries){ else if(importedlore.entries){
const entries:{[key:string]:{ const entries:{[key:string]:CCLorebook} = importedlore.entries
key:string[] lore.push(...convertExternalLorebook(entries))
comment:string
content:string
order:number
constant:boolean,
name:string,
keywords:string[],
priority:number
entry:string
secondary_keys:string[]
selective:boolean
forceActivation:boolean
keys:string[]
displayName:string
text:string
contextConfig?: {
budgetPriority:number
prefix:string
suffix:string
}
}} = importedlore.entries
for(const key in entries){
const currentLore = entries[key]
lore.push({
key: currentLore.key ? currentLore.key.join(', ') :
currentLore.keys ? currentLore.keys.join(', ') :
currentLore.keywords ? currentLore.keywords.join(', ') : '',
insertorder: currentLore.order ?? currentLore.priority ?? currentLore?.contextConfig?.budgetPriority ?? 0,
comment: currentLore.comment || currentLore.name || currentLore.displayName || '',
content: currentLore.content || currentLore.entry || currentLore.text || '',
mode: "normal",
alwaysActive: currentLore.constant ?? currentLore.forceActivation ?? false,
secondkey: currentLore.secondary_keys ? currentLore.secondary_keys.join(', ') : "",
selective: currentLore.selective ?? false
})
}
} }
if(mode === 'global'){ if(mode === 'global'){
db.characters[selectedID].globalLore = lore db.characters[selectedID].globalLore = lore
} }
else if(mode === 'sglobal'){
db.loreBook[db.loreBookPage].data = lore
}
else{ else{
db.characters[selectedID].chats[page].localLore = lore db.characters[selectedID].chats[page].localLore = lore
} }
@@ -388,6 +335,49 @@ export async function importLoreBook(mode:'global'|'local'|'sglobal'){
} }
} }
interface CCLorebook{
key:string[]
comment:string
content:string
order:number
constant:boolean,
name:string,
keywords:string[],
priority:number
entry:string
secondary_keys:string[]
selective:boolean
forceActivation:boolean
keys:string[]
displayName:string
text:string
contextConfig?: {
budgetPriority:number
prefix:string
suffix:string
}
}
export function convertExternalLorebook(entries:{[key:string]:CCLorebook}){
let lore:loreBook[] = []
for(const key in entries){
const currentLore = entries[key]
lore.push({
key: currentLore.key ? currentLore.key.join(', ') :
currentLore.keys ? currentLore.keys.join(', ') :
currentLore.keywords ? currentLore.keywords.join(', ') : '',
insertorder: currentLore.order ?? currentLore.priority ?? currentLore?.contextConfig?.budgetPriority ?? 0,
comment: currentLore.comment || currentLore.name || currentLore.displayName || '',
content: currentLore.content || currentLore.entry || currentLore.text || '',
mode: "normal",
alwaysActive: currentLore.constant ?? currentLore.forceActivation ?? false,
secondkey: currentLore.secondary_keys ? currentLore.secondary_keys.join(', ') : "",
selective: currentLore.selective ?? false
})
}
return lore
}
export async function exportLoreBook(mode:'global'|'local'|'sglobal'){ export async function exportLoreBook(mode:'global'|'local'|'sglobal'){
try { try {
const selectedID = get(selectedCharID) const selectedID = get(selectedCharID)
@@ -395,7 +385,6 @@ export async function exportLoreBook(mode:'global'|'local'|'sglobal'){
const page = mode === 'sglobal' ? -1 : db.characters[selectedID].chatPage const page = mode === 'sglobal' ? -1 : db.characters[selectedID].chatPage
const lore = const lore =
mode === 'global' ? db.characters[selectedID].globalLore : mode === 'global' ? db.characters[selectedID].globalLore :
mode === 'sglobal' ? db.loreBook[db.loreBookPage].data :
db.characters[selectedID].chats[page].localLore db.characters[selectedID].chats[page].localLore
const stringl = Buffer.from(JSON.stringify({ const stringl = Buffer.from(JSON.stringify({
type: 'risu', type: 'risu',

View File

@@ -1,11 +1,12 @@
import { language } from "src/lang" import { language } from "src/lang"
import { alertError, alertNormal } from "../alert" import { alertError, alertNormal } from "../alert"
import { DataBase, type customscript, type loreBook, type triggerscript } from "../storage/database" import { DataBase, setDatabase, type customscript, type loreBook, type triggerscript } from "../storage/database"
import { downloadFile } from "../storage/globalApi" import { downloadFile } from "../storage/globalApi"
import { get } from "svelte/store" import { get } from "svelte/store"
import { CurrentChat } from "../stores" import { CurrentChat } from "../stores"
import { selectSingleFile } from "../util" import { selectSingleFile } from "../util"
import { v4 } from "uuid" import { v4 } from "uuid"
import { convertExternalLorebook } from "./lorebook"
export interface RisuModule{ export interface RisuModule{
name: string name: string
@@ -26,24 +27,50 @@ export async function exportModule(module:RisuModule){
} }
export async function importModule(){ export async function importModule(){
const f = await selectSingleFile(['json']) const f = await selectSingleFile(['json', 'lorebook'])
if(!f){ if(!f){
return return
} }
const file = f.data const file = f.data
const db = get(DataBase)
try { try {
const importedModule = JSON.parse(Buffer.from(file).toString()) const importData = JSON.parse(Buffer.from(file).toString())
if(importedModule.type === 'risuModule'){ if(importData.type === 'risuModule'){
const db = get(DataBase)
if( if(
(!importedModule.name) (!importData.name)
|| (!importedModule.description) || (!importData.description)
|| (!importedModule.id) || (!importData.id)
){ ){
alertError(language.errors.noData) alertError(language.errors.noData)
} }
importedModule.id = v4() importData.id = v4()
db.modules.push(importedModule) db.modules.push(importData)
setDatabase(db)
return
}
if(importData.type === 'risu' && importData.data){
const lores:loreBook[] = importData.data
const importModule = {
name: importData.name || 'Imported Lorebook',
description: importData.description || 'Converted from risu lorebook',
lorebook: lores,
id: v4()
}
db.modules.push(importModule)
setDatabase(db)
return
}
if(importData.entries){
const lores:loreBook[] = convertExternalLorebook(importData.entries)
const importModule = {
name: importData.name || 'Imported Lorebook',
description: importData.description || 'Converted from external lorebook',
lorebook: lores,
id: v4()
}
db.modules.push(importModule)
setDatabase(db)
return
} }
} catch (error) { } catch (error) {
alertNormal(language.errors.noData) alertNormal(language.errors.noData)
@@ -65,8 +92,8 @@ export function getModuleLorebooks() {
const currentChat = get(CurrentChat) const currentChat = get(CurrentChat)
const db = get(DataBase) const db = get(DataBase)
if (!currentChat) return [] if (!currentChat) return []
const moduleIds = currentChat.modules ?? [] let moduleIds = currentChat.modules ?? []
moduleIds.concat(db.enabledModules) moduleIds = moduleIds.concat(db.enabledModules)
let lorebooks: loreBook[] = [] let lorebooks: loreBook[] = []
for (const moduleId of moduleIds) { for (const moduleId of moduleIds) {
const module = getModuleById(moduleId) const module = getModuleById(moduleId)
@@ -85,8 +112,8 @@ export function getModuleTriggers() {
const currentChat = get(CurrentChat) const currentChat = get(CurrentChat)
const db = get(DataBase) const db = get(DataBase)
if (!currentChat) return [] if (!currentChat) return []
const moduleIds = currentChat.modules ?? [] let moduleIds = currentChat.modules ?? []
moduleIds.concat(db.enabledModules) moduleIds = moduleIds.concat(db.enabledModules)
let triggers: triggerscript[] = [] let triggers: triggerscript[] = []
for (const moduleId of moduleIds) { for (const moduleId of moduleIds) {
const module = getModuleById(moduleId) const module = getModuleById(moduleId)
@@ -104,8 +131,8 @@ export function getModuleRegexScripts() {
const currentChat = get(CurrentChat) const currentChat = get(CurrentChat)
const db = get(DataBase) const db = get(DataBase)
if (!currentChat) return [] if (!currentChat) return []
const moduleIds = currentChat.modules ?? [] let moduleIds = currentChat.modules ?? []
moduleIds.concat(db.enabledModules) moduleIds = moduleIds.concat(db.enabledModules)
let customscripts: customscript[] = [] let customscripts: customscript[] = []
for (const moduleId of moduleIds) { for (const moduleId of moduleIds) {
const module = getModuleById(moduleId) const module = getModuleById(moduleId)

View File

@@ -15,7 +15,7 @@ import type { OobaChatCompletionRequestParams } from '../model/ooba';
export const DataBase = writable({} as any as Database) export const DataBase = writable({} as any as Database)
export const loadedStore = writable(false) export const loadedStore = writable(false)
export let appVer = "1.77.0" export let appVer = "1.78.2"
export let webAppSubVer = '' export let webAppSubVer = ''
export function setDatabase(data:Database){ export function setDatabase(data:Database){
@@ -591,6 +591,7 @@ export interface Database{
memoryLimitThickness?:number memoryLimitThickness?:number
modules: RisuModule[] modules: RisuModule[]
enabledModules: string[] enabledModules: string[]
sideMenuRerollButton?:boolean
} }
export interface customscript{ export interface customscript{

View File

@@ -1,7 +1,7 @@
import { writeBinaryFile,BaseDirectory, readBinaryFile, exists, createDir, readDir, removeFile } from "@tauri-apps/api/fs" import { writeBinaryFile,BaseDirectory, readBinaryFile, exists, createDir, readDir, removeFile } from "@tauri-apps/api/fs"
import { changeFullscreen, checkNullish, findCharacterbyId, sleep } from "../util" import { changeFullscreen, checkNullish, findCharacterbyId, sleep } from "../util"
import { convertFileSrc, invoke } from "@tauri-apps/api/tauri" import { convertFileSrc, invoke } from "@tauri-apps/api/tauri"
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4, v4 } from 'uuid';
import { appDataDir, join } from "@tauri-apps/api/path"; import { appDataDir, join } from "@tauri-apps/api/path";
import { get } from "svelte/store"; import { get } from "svelte/store";
import {open} from '@tauri-apps/api/shell' import {open} from '@tauri-apps/api/shell'
@@ -26,6 +26,7 @@ import { saveDbKei } from "../kei/backup";
import { Capacitor, CapacitorHttp } from '@capacitor/core'; import { Capacitor, CapacitorHttp } from '@capacitor/core';
import * as CapFS from '@capacitor/filesystem' import * as CapFS from '@capacitor/filesystem'
import { save } from "@tauri-apps/api/dialog"; import { save } from "@tauri-apps/api/dialog";
import type { RisuModule } from "../process/modules";
//@ts-ignore //@ts-ignore
export const isTauri = !!window.__TAURI__ export const isTauri = !!window.__TAURI__
@@ -985,6 +986,43 @@ async function checkNewFormat() {
db.formatversion = 3 db.formatversion = 3
} }
if(db.formatversion < 4){
db.modules ??= []
db.enabledModules ??=[]
//convert globallore and global regex to modules
if(db.globalscript && db.globalscript.length > 0){
const id = v4()
let regexModule:RisuModule = {
name: "Global Regex",
description: "Converted from legacy global regex",
id: id,
regex: cloneDeep(db.globalscript)
}
db.modules.push(regexModule)
db.enabledModules.push(id)
db.globalscript = []
}
if(db.loreBook && db.loreBook.length > 0){
const selIndex = db.loreBookPage
for(let i=0;i<db.loreBook.length;i++){
const id = v4()
let lbModule:RisuModule = {
name: db.loreBook[i].name || "Unnamed Global Lorebook",
description: "Converted from legacy global lorebook",
id: id,
lorebook: cloneDeep(db.loreBook[i].data)
}
db.modules.push(lbModule)
if(i === selIndex){
db.enabledModules.push(id)
}
db.globalscript = []
}
db.loreBook = []
}
db.formatversion = 4
}
if(!db.characterOrder){ if(!db.characterOrder){
db.characterOrder = [] db.characterOrder = []
} }

View File

@@ -1 +1 @@
{"version":"1.77.0"} {"version":"1.78.2"}