Merge branch 'main' of https://github.com/LightningHyperBlaze45654/RisuAI
This commit is contained in:
109
src/ts/alert.ts
109
src/ts/alert.ts
@@ -1,33 +1,34 @@
|
||||
import { get, writable } from "svelte/store"
|
||||
import { sleep } from "./util"
|
||||
import { language } from "../lang"
|
||||
import { isNodeServer, isTauri } from "./storage/globalApi"
|
||||
import { isNodeServer, isTauri } from "./globalApi.svelte"
|
||||
import { Capacitor } from "@capacitor/core"
|
||||
import { DataBase, type MessageGenerationInfo } from "./storage/database"
|
||||
import { getDatabase, type MessageGenerationInfo } from "./storage/database.svelte"
|
||||
import { alertStore as alertStoreImported } from "./stores.svelte"
|
||||
|
||||
interface alertData{
|
||||
export interface alertData{
|
||||
type: 'error'|'normal'|'none'|'ask'|'wait'|'selectChar'
|
||||
|'input'|'toast'|'wait2'|'markdown'|'select'|'login'
|
||||
|'tos'|'cardexport'|'requestdata'|'addchar'|'hypaV2'|'selectModule'
|
||||
|'chatOptions',
|
||||
|'chatOptions'|'pukmakkurit',
|
||||
msg: string,
|
||||
submsg?: string
|
||||
}
|
||||
|
||||
|
||||
export const alertStore = writable({
|
||||
type: 'none',
|
||||
msg: 'n',
|
||||
} as alertData)
|
||||
type AlertGenerationInfoStoreData = {
|
||||
genInfo: MessageGenerationInfo,
|
||||
idx: number
|
||||
}
|
||||
export const alertGenerationInfoStore = writable<AlertGenerationInfoStoreData>(null)
|
||||
export const alertStore = {
|
||||
set: (d:alertData) => {
|
||||
alertStoreImported.set(d)
|
||||
}
|
||||
}
|
||||
|
||||
export function alertError(msg:string){
|
||||
console.error(msg)
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
|
||||
if(typeof(msg) !== 'string'){
|
||||
try{
|
||||
@@ -55,7 +56,7 @@ export function alertError(msg:string){
|
||||
(!isTauri && !isNodeServer && !Capacitor.isNativePlatform()) ? language.errors.networkFetchWeb : language.errors.networkFetch
|
||||
}
|
||||
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'error',
|
||||
'msg': msg,
|
||||
'submsg': submsg
|
||||
@@ -63,19 +64,19 @@ export function alertError(msg:string){
|
||||
}
|
||||
|
||||
export function alertNormal(msg:string){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'normal',
|
||||
'msg': msg
|
||||
})
|
||||
}
|
||||
|
||||
export async function alertNormalWait(msg:string){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'normal',
|
||||
'msg': msg
|
||||
})
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
@@ -83,73 +84,73 @@ export async function alertNormalWait(msg:string){
|
||||
}
|
||||
|
||||
export async function alertAddCharacter() {
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'addchar',
|
||||
'msg': language.addCharacter
|
||||
})
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return get(alertStore).msg
|
||||
return get(alertStoreImported).msg
|
||||
}
|
||||
|
||||
export async function alertChatOptions() {
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'chatOptions',
|
||||
'msg': language.chatOptions
|
||||
})
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return parseInt(get(alertStore).msg)
|
||||
return parseInt(get(alertStoreImported).msg)
|
||||
}
|
||||
|
||||
export async function alertLogin(){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'login',
|
||||
'msg': 'login'
|
||||
})
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return get(alertStore).msg
|
||||
return get(alertStoreImported).msg
|
||||
}
|
||||
|
||||
export async function alertSelect(msg:string[]){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'select',
|
||||
'msg': msg.join('||')
|
||||
})
|
||||
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return get(alertStore).msg
|
||||
return get(alertStoreImported).msg
|
||||
}
|
||||
|
||||
export async function alertErrorWait(msg:string){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'wait2',
|
||||
'msg': msg
|
||||
})
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
@@ -157,25 +158,25 @@ export async function alertErrorWait(msg:string){
|
||||
}
|
||||
|
||||
export function alertMd(msg:string){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'markdown',
|
||||
'msg': msg
|
||||
})
|
||||
}
|
||||
|
||||
export function doingAlert(){
|
||||
return get(alertStore).type !== 'none' && get(alertStore).type !== 'toast'
|
||||
return get(alertStoreImported).type !== 'none' && get(alertStoreImported).type !== 'toast' && get(alertStoreImported).type !== 'wait'
|
||||
}
|
||||
|
||||
export function alertToast(msg:string){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'toast',
|
||||
'msg': msg
|
||||
})
|
||||
}
|
||||
|
||||
export function alertWait(msg:string){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'wait',
|
||||
'msg': msg
|
||||
})
|
||||
@@ -184,61 +185,61 @@ export function alertWait(msg:string){
|
||||
|
||||
|
||||
export function alertClear(){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'none',
|
||||
'msg': ''
|
||||
})
|
||||
}
|
||||
|
||||
export async function alertSelectChar(){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'selectChar',
|
||||
'msg': ''
|
||||
})
|
||||
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return get(alertStore).msg
|
||||
return get(alertStoreImported).msg
|
||||
}
|
||||
|
||||
export async function alertConfirm(msg:string){
|
||||
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'ask',
|
||||
'msg': msg
|
||||
})
|
||||
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return get(alertStore).msg === 'yes'
|
||||
return get(alertStoreImported).msg === 'yes'
|
||||
}
|
||||
|
||||
export async function alertCardExport(type:string = ''){
|
||||
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'cardexport',
|
||||
'msg': '',
|
||||
'submsg': type
|
||||
})
|
||||
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return JSON.parse(get(alertStore).msg) as {
|
||||
return JSON.parse(get(alertStoreImported).msg) as {
|
||||
type: string,
|
||||
type2: string,
|
||||
}
|
||||
@@ -250,19 +251,19 @@ export async function alertTOS(){
|
||||
return true
|
||||
}
|
||||
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'tos',
|
||||
'msg': 'tos'
|
||||
})
|
||||
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
if(get(alertStore).msg === 'yes'){
|
||||
if(get(alertStoreImported).msg === 'yes'){
|
||||
localStorage.setItem('tos2', 'true')
|
||||
return true
|
||||
}
|
||||
@@ -272,48 +273,48 @@ export async function alertTOS(){
|
||||
|
||||
export async function alertInput(msg:string){
|
||||
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'input',
|
||||
'msg': msg
|
||||
})
|
||||
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
}
|
||||
|
||||
return get(alertStore).msg
|
||||
return get(alertStoreImported).msg
|
||||
}
|
||||
|
||||
export async function alertModuleSelect(){
|
||||
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'selectModule',
|
||||
'msg': ''
|
||||
})
|
||||
|
||||
while(true){
|
||||
if (get(alertStore).type === 'none'){
|
||||
if (get(alertStoreImported).type === 'none'){
|
||||
break
|
||||
}
|
||||
await sleep(10)
|
||||
await sleep(20)
|
||||
}
|
||||
|
||||
return get(alertStore).msg
|
||||
return get(alertStoreImported).msg
|
||||
}
|
||||
|
||||
export function alertRequestData(info:AlertGenerationInfoStoreData){
|
||||
alertGenerationInfoStore.set(info)
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'requestdata',
|
||||
'msg': info.genInfo.generationId ?? 'none'
|
||||
})
|
||||
}
|
||||
|
||||
export function showHypaV2Alert(){
|
||||
alertStore.set({
|
||||
alertStoreImported.set({
|
||||
'type': 'hypaV2',
|
||||
'msg': ""
|
||||
})
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { get, writable, type Writable } from "svelte/store"
|
||||
import { alertCardExport, alertConfirm, alertError, alertInput, alertMd, alertNormal, alertSelect, alertStore, alertTOS, alertWait } from "./alert"
|
||||
import { DataBase, defaultSdDataFunc, type character, setDatabase, type customscript, type loreSettings, type loreBook, type triggerscript, importPreset, type groupChat } from "./storage/database"
|
||||
import { defaultSdDataFunc, type character, setDatabase, type customscript, type loreSettings, type loreBook, type triggerscript, importPreset, type groupChat, setCurrentCharacter, getCurrentCharacter, getDatabase, setDatabaseLite, appVer } from "./storage/database.svelte"
|
||||
import { checkNullish, decryptBuffer, encryptBuffer, isKnownUri, selectFileByDom, selectMultipleFile, sleep } from "./util"
|
||||
import { language } from "src/lang"
|
||||
import { v4 as uuidv4, v4 } from 'uuid';
|
||||
import { characterFormatUpdate } from "./characters"
|
||||
import { AppendableBuffer, BlankWriter, checkCharOrder, downloadFile, isNodeServer, isTauri, loadAsset, LocalWriter, openURL, readImage, saveAsset, VirtualWriter } from "./storage/globalApi"
|
||||
import { CurrentCharacter, SettingsMenuIndex, ShowRealmFrameStore, selectedCharID, settingsOpen } from "./stores"
|
||||
import { convertImage, hasher } from "./parser"
|
||||
import { AppendableBuffer, BlankWriter, checkCharOrder, downloadFile, isNodeServer, isTauri, loadAsset, LocalWriter, openURL, readImage, saveAsset, VirtualWriter } from "./globalApi.svelte"
|
||||
import { SettingsMenuIndex, ShowRealmFrameStore, selectedCharID, settingsOpen } from "./stores.svelte"
|
||||
import { convertImage, hasher } from "./parser.svelte"
|
||||
import { CCardLib, type CharacterCardV3, type LorebookEntry } from '@risuai/ccardlib'
|
||||
import { reencodeImage } from "./process/files/image"
|
||||
import { PngChunk } from "./pngChunk"
|
||||
@@ -15,6 +15,8 @@ import type { OnnxModelFiles } from "./process/transformers"
|
||||
import { CharXReader, CharXWriter } from "./process/processzip"
|
||||
import { Capacitor } from "@capacitor/core"
|
||||
import { exportModule, readModule, type RisuModule } from "./process/modules"
|
||||
import { readFile } from "@tauri-apps/plugin-fs"
|
||||
import { onOpenUrl } from '@tauri-apps/plugin-deep-link';
|
||||
|
||||
export const hubURL = "https://sv.risuai.xyz"
|
||||
|
||||
@@ -39,9 +41,10 @@ export async function importCharacter() {
|
||||
}
|
||||
}
|
||||
|
||||
async function importCharacterProcess(f:{
|
||||
export async function importCharacterProcess(f:{
|
||||
name: string;
|
||||
data: Uint8Array|File|ReadableStream<Uint8Array>
|
||||
lightningRealmImport?:boolean
|
||||
}) {
|
||||
if(f.name.endsWith('json')){
|
||||
if(f.data instanceof ReadableStream){
|
||||
@@ -50,13 +53,13 @@ async function importCharacterProcess(f:{
|
||||
const data = f.data instanceof Uint8Array ? f.data : new Uint8Array(await f.data.arrayBuffer())
|
||||
const da = JSON.parse(Buffer.from(data).toString('utf-8'))
|
||||
if(await importCharacterCardSpec(da)){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
return db.characters.length - 1
|
||||
}
|
||||
if((da.char_name || da.name) && (da.char_persona || da.description) && (da.char_greeting || da.first_mes)){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
db.characters.push(convertOffSpecCards(da))
|
||||
DataBase.set(db)
|
||||
setDatabaseLite(db)
|
||||
alertNormal(language.importedCharacter)
|
||||
return
|
||||
}
|
||||
@@ -66,7 +69,7 @@ async function importCharacterProcess(f:{
|
||||
}
|
||||
}
|
||||
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
db.statics.imports += 1
|
||||
|
||||
if(f.name.endsWith('charx')){
|
||||
@@ -97,7 +100,7 @@ async function importCharacterProcess(f:{
|
||||
card.data.extensions.risuai.customScripts = md.regex ?? []
|
||||
}
|
||||
await importCharacterCardSpec(card, undefined, 'normal', reader.assets)
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
return db.characters.length - 1
|
||||
}
|
||||
|
||||
@@ -121,6 +124,9 @@ async function importCharacterProcess(f:{
|
||||
returnTrimed: true
|
||||
})
|
||||
const assets:{[key:string]:string} = {}
|
||||
let queueFetch:Promise<Response>[] = []
|
||||
let queueFetchKey:string[] = []
|
||||
let queueFetchData:Buffer[] = []
|
||||
for await (const chunk of readGenerator){
|
||||
console.log(chunk)
|
||||
if(!chunk){
|
||||
@@ -147,10 +153,53 @@ async function importCharacterProcess(f:{
|
||||
const assetIndex = chunk.key.replace('chara-ext-asset_:', '').replace('chara-ext-asset_', '')
|
||||
alertWait('Loading... (Reading Asset ' + assetIndex + ')' )
|
||||
const assetData = Buffer.from(chunk.value, 'base64')
|
||||
if(db.account?.useSync && f.lightningRealmImport){
|
||||
const id = await hasher(assetData)
|
||||
const xid = 'assets/' + id + '.png'
|
||||
queueFetchKey.push(assetIndex)
|
||||
queueFetchData.push(assetData)
|
||||
queueFetch.push(fetch('https://sv.risuai.xyz/rs/' + xid))
|
||||
assets[assetIndex] = 'xid:' + xid
|
||||
if(queueFetch.length > 10){
|
||||
const res = await Promise.all(queueFetch)
|
||||
for(let i=0;i<res.length;i++){
|
||||
if(res[i].status !== 200){
|
||||
const assetId = await saveAsset(queueFetchData[i])
|
||||
assets[queueFetchKey[i]] = assetId
|
||||
}
|
||||
else{
|
||||
assets[queueFetchKey[i]] = assets[queueFetchKey[i]].replace('xid:', '')
|
||||
}
|
||||
}
|
||||
queueFetch = []
|
||||
queueFetchKey = []
|
||||
queueFetchData = []
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
const assetId = await saveAsset(assetData)
|
||||
assets[assetIndex] = assetId
|
||||
}
|
||||
}
|
||||
|
||||
if(queueFetch.length > 0){
|
||||
const res = await Promise.all(queueFetch)
|
||||
for(let i=0;i<res.length;i++){
|
||||
if(res[i].status !== 200){
|
||||
const assetId = await saveAsset(queueFetchData[i])
|
||||
assets[queueFetchKey[i]] = assetId
|
||||
}
|
||||
else{
|
||||
assets[queueFetchKey[i]] = assets[queueFetchKey[i]].replace('xid:', '')
|
||||
}
|
||||
}
|
||||
queueFetch = []
|
||||
queueFetchKey = []
|
||||
queueFetchData = []
|
||||
}
|
||||
|
||||
if(!readedChara && !readedCCv3){
|
||||
alertError(language.errors.noData)
|
||||
return
|
||||
@@ -191,7 +240,7 @@ async function importCharacterProcess(f:{
|
||||
const decrypted = await decryptBuffer(encrypted, password)
|
||||
const charaData:CharacterCardV2Risu = JSON.parse(Buffer.from(decrypted).toString('utf-8'))
|
||||
if(await importCharacterCardSpec(charaData, img, "normal", assets)){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
return db.characters.length - 1
|
||||
}
|
||||
else{
|
||||
@@ -208,7 +257,7 @@ async function importCharacterProcess(f:{
|
||||
try {
|
||||
const charaData:CharacterCardV2Risu = JSON.parse(Buffer.from(decrypted).toString('utf-8'))
|
||||
if(await importCharacterCardSpec(charaData, img, "normal", assets)){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
return db.characters.length - 1
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -219,28 +268,26 @@ async function importCharacterProcess(f:{
|
||||
|
||||
}
|
||||
}
|
||||
else {
|
||||
const parsed = JSON.parse(Buffer.from(readedChara, 'base64').toString('utf-8'))
|
||||
//fix readedChara version pointing number instead of string because of previous version
|
||||
if(typeof (parsed as CharacterCardV2Risu)?.data?.character_version === 'number'){
|
||||
(parsed as CharacterCardV2Risu).data.character_version = (parsed as CharacterCardV2Risu).data.character_version.toString()
|
||||
}
|
||||
|
||||
const checkedVersion = CCardLib.character.check(parsed)
|
||||
if(checkedVersion === 'v2' || checkedVersion === 'v3'){
|
||||
if(await importCharacterCardSpec(parsed, img, "normal", assets)){
|
||||
let db = get(DataBase)
|
||||
return db.characters.length - 1
|
||||
}
|
||||
}
|
||||
const parsed = JSON.parse(Buffer.from(readedChara, 'base64').toString('utf-8'))
|
||||
//fix readedChara version pointing number instead of string because of previous version
|
||||
if(typeof (parsed as CharacterCardV2Risu)?.data?.character_version === 'number'){
|
||||
(parsed as CharacterCardV2Risu).data.character_version = (parsed as CharacterCardV2Risu).data.character_version.toString()
|
||||
}
|
||||
const charaData:OldTavernChar = JSON.parse(Buffer.from(readedChara, 'base64').toString('utf-8'))
|
||||
console.log(charaData)
|
||||
const imgp = await saveAsset(await reencodeImage(img))
|
||||
db.characters.push(convertOffSpecCards(charaData, imgp))
|
||||
DataBase.set(db)
|
||||
alertNormal(language.importedCharacter)
|
||||
|
||||
if(parsed.spec !== 'chara_card_v2' && parsed.spec !== 'chara_card_v3'){
|
||||
const charaData:OldTavernChar = JSON.parse(Buffer.from(readedChara, 'base64').toString('utf-8'))
|
||||
console.log(charaData)
|
||||
const imgp = await saveAsset(await reencodeImage(img))
|
||||
db.characters.push(convertOffSpecCards(charaData, imgp))
|
||||
setDatabaseLite(db)
|
||||
alertNormal(language.importedCharacter)
|
||||
return db.characters.length - 1
|
||||
}
|
||||
await importCharacterCardSpec(parsed, img, "normal", assets)
|
||||
|
||||
db = getDatabase()
|
||||
return db.characters.length - 1
|
||||
|
||||
}
|
||||
|
||||
export const getRealmInfo = async (realmPath:string) => {
|
||||
@@ -299,12 +346,27 @@ export async function characterURLImport() {
|
||||
|
||||
|
||||
const hash = location.hash
|
||||
if(hash.startsWith('#import=')){
|
||||
location.hash = ''
|
||||
const url = hash.replace('#import=', '')
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method: 'GET',
|
||||
})
|
||||
const data = new Uint8Array(await res.arrayBuffer())
|
||||
await importFile(getFileName(res), data)
|
||||
checkCharOrder()
|
||||
} catch (error) {
|
||||
alertError(language.errors.noData)
|
||||
return null
|
||||
}
|
||||
}
|
||||
if(hash.startsWith('#import_module=')){
|
||||
const data = hash.replace('#import_module=', '')
|
||||
const importData = JSON.parse(Buffer.from(decodeURIComponent(data), 'base64').toString('utf-8'))
|
||||
importData.id = v4()
|
||||
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(importData.lowLevelAccess){
|
||||
const conf = await alertConfirm(language.lowLevelAccessConfirm)
|
||||
if(!conf){
|
||||
@@ -348,7 +410,7 @@ export async function characterURLImport() {
|
||||
const module = new Uint8Array(await data.arrayBuffer())
|
||||
const md = await readModule(Buffer.from(module))
|
||||
md.id = v4()
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
db.modules.push(md)
|
||||
setDatabase(db)
|
||||
alertNormal(language.successImport)
|
||||
@@ -373,31 +435,7 @@ export async function characterURLImport() {
|
||||
for(const f of files){
|
||||
const file = await f.getFile()
|
||||
const data = new Uint8Array(await file.arrayBuffer())
|
||||
if(f.name.endsWith('.charx')){
|
||||
await importCharacterProcess({
|
||||
name: f.name,
|
||||
data: data
|
||||
})
|
||||
}
|
||||
if(f.name.endsWith('.risupreset') || f.name.endsWith('.risup')){
|
||||
await importPreset({
|
||||
name: f.name,
|
||||
data: data
|
||||
})
|
||||
SettingsMenuIndex.set(1)
|
||||
settingsOpen.set(true)
|
||||
alertNormal(language.successImport)
|
||||
}
|
||||
if(f.name.endsWith('risum')){
|
||||
const md = await readModule(Buffer.from(data))
|
||||
md.id = v4()
|
||||
const db = get(DataBase)
|
||||
db.modules.push(md)
|
||||
setDatabase(db)
|
||||
alertNormal(language.successImport)
|
||||
SettingsMenuIndex.set(14)
|
||||
settingsOpen.set(true)
|
||||
}
|
||||
await importFile(f.name, data);
|
||||
}
|
||||
}
|
||||
//@ts-ignore
|
||||
@@ -408,13 +446,113 @@ export async function characterURLImport() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if("tauriOpenedFiles" in window){
|
||||
//@ts-ignore
|
||||
const files:string[] = window.tauriOpenedFiles
|
||||
if(files){
|
||||
for(const file of files){
|
||||
const data = await readFile(file)
|
||||
await importFile(file, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isTauri){
|
||||
await onOpenUrl((urls) => {
|
||||
for(const url of urls){
|
||||
const splited = url.split('/')
|
||||
const id = splited[splited.length - 1]
|
||||
const type = splited[splited.length - 2]
|
||||
switch(type){
|
||||
case 'realm':{
|
||||
downloadRisuHub(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function importFile(name:string, data:Uint8Array) {
|
||||
if(name.endsWith('.charx') || name.endsWith('.png')){
|
||||
await importCharacterProcess({
|
||||
name: name,
|
||||
data: data
|
||||
})
|
||||
return
|
||||
}
|
||||
if(name.endsWith('.risupreset') || name.endsWith('.risup')){
|
||||
await importPreset({
|
||||
name: name,
|
||||
data: data
|
||||
})
|
||||
SettingsMenuIndex.set(1)
|
||||
settingsOpen.set(true)
|
||||
alertNormal(language.successImport)
|
||||
return
|
||||
}
|
||||
if(name.endsWith('risum')){
|
||||
const md = await readModule(Buffer.from(data))
|
||||
md.id = v4()
|
||||
const db = getDatabase()
|
||||
db.modules.push(md)
|
||||
setDatabase(db)
|
||||
alertNormal(language.successImport)
|
||||
SettingsMenuIndex.set(14)
|
||||
settingsOpen.set(true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function getFileName(res : Response) : string {
|
||||
return getFromContent(res.headers.get('content-disposition')) || getFromURL(res.url);
|
||||
|
||||
function getFromContent(contentDisposition : string) {
|
||||
if (!contentDisposition) return null;
|
||||
const pattern = /filename\*=UTF-8''([^"';\n]+)|filename[^;\n=]*=["']?([^"';\n]+)["']?/;
|
||||
const matches = contentDisposition.match(pattern);
|
||||
if (matches) {
|
||||
if (matches[1]) {
|
||||
return decodeURIComponent(matches[1]);
|
||||
} else if (matches[2]) {
|
||||
return matches[2];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getFromURL(url : string) : string {
|
||||
try {
|
||||
const path = new URL(url).pathname;
|
||||
return path.substring(path.lastIndexOf('/') + 1);
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function convertOffSpecCards(charaData:OldTavernChar|CharacterCardV2Risu, imgp:string|undefined = undefined):character{
|
||||
const data = charaData.spec_version === '2.0' ? charaData.data : charaData
|
||||
console.log("Off spec detected, converting")
|
||||
const charbook = charaData.spec_version === '2.0' ? charaData.data.character_book : null
|
||||
let lorebook:loreBook[] = []
|
||||
let loresettings:undefined|loreSettings = undefined
|
||||
let loreExt:undefined|any = undefined
|
||||
if(charbook){
|
||||
const a = convertCharbook({
|
||||
lorebook,
|
||||
charbook,
|
||||
loresettings,
|
||||
loreExt
|
||||
})
|
||||
|
||||
lorebook = a.lorebook
|
||||
loresettings = a.loresettings
|
||||
loreExt = a.loreExt
|
||||
}
|
||||
|
||||
return {
|
||||
name: data.name ?? 'unknown name',
|
||||
firstMessage: data.first_mes ?? 'unknown first message',
|
||||
@@ -430,7 +568,7 @@ function convertOffSpecCards(charaData:OldTavernChar|CharacterCardV2Risu, imgp:s
|
||||
image: imgp,
|
||||
emotionImages: [],
|
||||
bias: [],
|
||||
globalLore: [],
|
||||
globalLore: lorebook,
|
||||
viewScreen: 'none',
|
||||
chaId: uuidv4(),
|
||||
sdData: defaultSdDataFunc(),
|
||||
@@ -449,13 +587,16 @@ function convertOffSpecCards(charaData:OldTavernChar|CharacterCardV2Risu, imgp:s
|
||||
firstMsgIndex: -1,
|
||||
replaceGlobalNote: "",
|
||||
triggerscript: [],
|
||||
additionalText: ''
|
||||
additionalText: '',
|
||||
loreExt: loreExt,
|
||||
loreSettings: loresettings,
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export async function exportChar(charaID:number):Promise<string> {
|
||||
const db = get(DataBase)
|
||||
let char = structuredClone(db.characters[charaID])
|
||||
const db = getDatabase({snapshot: true})
|
||||
let char = safeStructuredClone(db.characters[charaID])
|
||||
|
||||
if(char.type === 'group'){
|
||||
return ''
|
||||
@@ -488,12 +629,14 @@ async function importCharacterCardSpec(card:CharacterCardV2Risu|CharacterCardV3,
|
||||
return false
|
||||
}
|
||||
|
||||
console.log(`Importing ${card.spec}, mode is ${mode}`)
|
||||
|
||||
const data = card.data
|
||||
console.log(card)
|
||||
let im = img ? await saveAsset(await reencodeImage(img)) : undefined
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
|
||||
const risuext = structuredClone(data.extensions.risuai)
|
||||
const risuext = safeStructuredClone(data.extensions.risuai)
|
||||
let emotions:[string, string][] = []
|
||||
let bias:[string, number][] = []
|
||||
let viewScreen: "none" | "emotion" | "imggen" = 'none'
|
||||
@@ -680,40 +823,19 @@ async function importCharacterCardSpec(card:CharacterCardV2Risu|CharacterCardV3,
|
||||
let loresettings:undefined|loreSettings = undefined
|
||||
let loreExt:undefined|any = undefined
|
||||
if(charbook){
|
||||
if((!checkNullish(charbook.recursive_scanning)) &&
|
||||
(!checkNullish(charbook.scan_depth)) &&
|
||||
(!checkNullish(charbook.token_budget))){
|
||||
loresettings = {
|
||||
tokenBudget:charbook.token_budget,
|
||||
scanDepth:charbook.scan_depth,
|
||||
recursiveScanning: charbook.recursive_scanning,
|
||||
fullWordMatching: charbook?.extensions?.risu_fullWordMatching ?? false,
|
||||
}
|
||||
}
|
||||
|
||||
loreExt = charbook.extensions
|
||||
|
||||
for(const book of charbook.entries){
|
||||
lorebook.push({
|
||||
key: book.keys.join(', '),
|
||||
secondkey: book.secondary_keys?.join(', ') ?? '',
|
||||
insertorder: book.insertion_order,
|
||||
comment: book.name ?? book.comment ?? "",
|
||||
content: book.content,
|
||||
mode: "normal",
|
||||
alwaysActive: book.constant ?? false,
|
||||
selective: book.selective ?? false,
|
||||
extentions: {...book.extensions, risu_case_sensitive: book.case_sensitive},
|
||||
activationPercent: book.extensions?.risu_activationPercent,
|
||||
loreCache: book.extensions?.risu_loreCache ?? null,
|
||||
//@ts-ignore
|
||||
useRegex: book.use_regex ?? false
|
||||
})
|
||||
}
|
||||
const a = convertCharbook({
|
||||
lorebook,
|
||||
charbook,
|
||||
loresettings,
|
||||
loreExt
|
||||
})
|
||||
|
||||
lorebook = a.lorebook
|
||||
loresettings = a.loresettings
|
||||
loreExt = a.loreExt
|
||||
}
|
||||
|
||||
let ext = structuredClone(data?.extensions ?? {})
|
||||
let ext = safeStructuredClone(data?.extensions ?? {})
|
||||
|
||||
for(const key in ext){
|
||||
if(key === 'risuai'){
|
||||
@@ -752,7 +874,7 @@ async function importCharacterCardSpec(card:CharacterCardV2Risu|CharacterCardV3,
|
||||
alternateGreetings:data.alternate_greetings ?? [],
|
||||
tags:data.tags ?? [],
|
||||
creator:data.creator ?? '',
|
||||
characterVersion: `${data.character_version}` ?? '',
|
||||
characterVersion: `${data.character_version}` || '',
|
||||
personality:data.personality ?? '',
|
||||
scenario:data.scenario ?? '',
|
||||
firstMsgIndex: -1,
|
||||
@@ -804,6 +926,113 @@ async function importCharacterCardSpec(card:CharacterCardV2Risu|CharacterCardV3,
|
||||
|
||||
}
|
||||
|
||||
function convertCharbook(arg:{
|
||||
lorebook:loreBook[]
|
||||
charbook:CharacterBook
|
||||
loresettings:loreSettings
|
||||
loreExt:any
|
||||
}){
|
||||
let {lorebook, loresettings, loreExt, charbook} = arg
|
||||
if((!checkNullish(charbook.recursive_scanning)) &&
|
||||
(!checkNullish(charbook.scan_depth)) &&
|
||||
(!checkNullish(charbook.token_budget))){
|
||||
loresettings = {
|
||||
tokenBudget:charbook.token_budget,
|
||||
scanDepth:charbook.scan_depth,
|
||||
recursiveScanning: charbook.recursive_scanning,
|
||||
fullWordMatching: charbook?.extensions?.risu_fullWordMatching ?? false,
|
||||
}
|
||||
}
|
||||
|
||||
loreExt = charbook.extensions
|
||||
|
||||
for(const book of charbook.entries){
|
||||
let content = book.content
|
||||
|
||||
if(book.use_regex && !book.keys?.[0]?.startsWith('/')){
|
||||
book.use_regex = false
|
||||
}
|
||||
|
||||
//extention migration
|
||||
const extensions = book.extensions ?? {}
|
||||
|
||||
if(extensions.useProbability && extensions.probability !== undefined && extensions.probability !== 100){
|
||||
content = `@@probability ${extensions.probability}\n` + content
|
||||
delete extensions.useProbability
|
||||
delete extensions.probability
|
||||
}
|
||||
if(extensions.position === 4 && typeof extensions.depth === 'number' && typeof(extensions.role) === 'number'){
|
||||
content = `@@depth ${extensions.depth}\n@@role ${['system','user','assistant'][extensions.role]}\n` + content
|
||||
delete extensions.position
|
||||
delete extensions.depth
|
||||
delete extensions.role
|
||||
}
|
||||
if(typeof(extensions.selectiveLogic) === 'number' && book.secondary_keys && book.secondary_keys.length > 0){
|
||||
switch(extensions.selectiveLogic){
|
||||
case 0:{
|
||||
if(!book.secondary_keys || book.secondary_keys.length === 0){
|
||||
book.selective = false
|
||||
}
|
||||
break
|
||||
}
|
||||
case 1:{
|
||||
book.selective = false
|
||||
content = `@@exclude_keys_all ${book.secondary_keys.join(',')}\n` + content
|
||||
break
|
||||
}
|
||||
case 2:{
|
||||
book.selective = false
|
||||
for(const secKey of book.secondary_keys){
|
||||
content = `@@exclude_keys ${secKey}\n` + content
|
||||
}
|
||||
break
|
||||
}
|
||||
case 3:{
|
||||
book.selective = false
|
||||
for(const secKey of book.secondary_keys){
|
||||
content = `@@additional_keys ${secKey}\n` + content
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if(typeof extensions.delay === 'number' && extensions.delay > 0){
|
||||
content = `@@activate_only_after ${extensions.delay}\n` + content
|
||||
delete extensions.delay
|
||||
}
|
||||
if(extensions.match_whole_words === true){
|
||||
content = `@@match_full_word\n` + content
|
||||
delete extensions.match_whole_words
|
||||
}
|
||||
if(extensions.match_whole_words === false){
|
||||
content = `@@match_partial_word\n` + content
|
||||
delete extensions.match_whole_words
|
||||
}
|
||||
|
||||
lorebook.push({
|
||||
key: book.keys.join(', '),
|
||||
secondkey: book.secondary_keys?.join(', ') ?? '',
|
||||
insertorder: book.insertion_order,
|
||||
comment: book.name ?? book.comment ?? "",
|
||||
content: content,
|
||||
mode: "normal",
|
||||
alwaysActive: book.constant ?? false,
|
||||
selective: book.selective ?? false,
|
||||
extentions: {...extensions, risu_case_sensitive: book.case_sensitive},
|
||||
activationPercent: book.extensions?.risu_activationPercent,
|
||||
loreCache: book.extensions?.risu_loreCache ?? null,
|
||||
//@ts-ignore
|
||||
useRegex: book.use_regex ?? false
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
lorebook,
|
||||
loresettings,
|
||||
loreExt
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function createBaseV2(char:character) {
|
||||
@@ -817,7 +1046,7 @@ async function createBaseV2(char:character) {
|
||||
key:string
|
||||
data:string[]
|
||||
}
|
||||
} = structuredClone(lore.extentions ?? {})
|
||||
} = safeStructuredClone(lore.extentions ?? {})
|
||||
|
||||
let caseSensitive = ext.risu_case_sensitive ?? false
|
||||
ext.risu_activationPercent = lore.activationPercent
|
||||
@@ -864,7 +1093,7 @@ async function createBaseV2(char:character) {
|
||||
},
|
||||
tags: char.tags ?? [],
|
||||
creator: char.additionalData?.creator ?? '',
|
||||
character_version: `${char.additionalData?.character_version}` ?? '',
|
||||
character_version: `${char.additionalData?.character_version}` || '',
|
||||
extensions: {
|
||||
risuai: {
|
||||
// emotions: char.emotionImages,
|
||||
@@ -1147,7 +1376,7 @@ export function createBaseV3(char:character){
|
||||
uri: string
|
||||
name: string
|
||||
ext: string
|
||||
}> = structuredClone(char.ccAssets ?? [])
|
||||
}> = safeStructuredClone(char.ccAssets ?? [])
|
||||
|
||||
if(char.additionalAssets){
|
||||
for(const asset of char.additionalAssets){
|
||||
@@ -1186,7 +1415,7 @@ export function createBaseV3(char:character){
|
||||
key:string
|
||||
data:string[]
|
||||
}
|
||||
} = structuredClone(lore.extentions ?? {})
|
||||
} = safeStructuredClone(lore.extentions ?? {})
|
||||
|
||||
let caseSensitive = ext.risu_case_sensitive ?? false
|
||||
ext.risu_activationPercent = lore.activationPercent
|
||||
@@ -1234,7 +1463,7 @@ export function createBaseV3(char:character){
|
||||
},
|
||||
tags: char.tags ?? [],
|
||||
creator: char.additionalData?.creator ?? '',
|
||||
character_version: `${char.additionalData?.character_version}` ?? '',
|
||||
character_version: `${char.additionalData?.character_version}` || '',
|
||||
extensions: {
|
||||
risuai: {
|
||||
bias: char.bias,
|
||||
@@ -1286,7 +1515,7 @@ export async function shareRisuHub2(char:character, arg:{
|
||||
update: boolean
|
||||
}) {
|
||||
try {
|
||||
char = structuredClone(char)
|
||||
char = safeStructuredClone(char)
|
||||
char.license = arg.license
|
||||
let tagList = arg.tag.split(',')
|
||||
|
||||
@@ -1320,8 +1549,8 @@ export async function shareRisuHub2(char:character, arg:{
|
||||
headers: {
|
||||
"Content-Type": 'image/png',
|
||||
"x-risu-api-version": "4",
|
||||
"x-risu-token": get(DataBase)?.account?.token,
|
||||
'x-risu-username': arg.anon ? '' : (get(DataBase)?.account?.id),
|
||||
"x-risu-token": getDatabase()?.account?.token,
|
||||
'x-risu-username': arg.anon ? '' : (getDatabase()?.account?.id),
|
||||
'x-risu-debug': 'true',
|
||||
'x-risu-update-id': arg.update ? (char.realmId ?? 'null') : 'null'
|
||||
}
|
||||
@@ -1336,12 +1565,12 @@ export async function shareRisuHub2(char:character, arg:{
|
||||
else{
|
||||
const resJSON = await res.json()
|
||||
alertMd(resJSON.message)
|
||||
const currentChar = get(CurrentCharacter)
|
||||
const currentChar = getCurrentCharacter()
|
||||
if(currentChar.type === 'group'){
|
||||
return
|
||||
}
|
||||
currentChar.realmId = resJSON.id
|
||||
CurrentCharacter.set(currentChar)
|
||||
setCurrentCharacter(currentChar)
|
||||
}
|
||||
} catch (error) {
|
||||
alertError(`${error}`)
|
||||
@@ -1382,7 +1611,11 @@ export async function getRisuHub(arg:{
|
||||
arg.search += ' __shared'
|
||||
const stringArg = `search==${arg.search}&&page==${arg.page}&&nsfw==${arg.nsfw}&&sort==${arg.sort}&&web==${(!isNodeServer && !Capacitor.isNativePlatform() && !isTauri) ? 'web' : 'other'}`
|
||||
|
||||
const da = await fetch(hubURL + '/realm/' + encodeURIComponent(stringArg))
|
||||
const da = await fetch(hubURL + '/realm/' + encodeURIComponent(stringArg), {
|
||||
headers: {
|
||||
"x-risuai-info": appVer + ';' + (isNodeServer ? 'node' : (Capacitor.isNativePlatform() ? 'capacitor' : isTauri ? 'tauri' : 'web'))
|
||||
}
|
||||
})
|
||||
if(da.status !== 200){
|
||||
return []
|
||||
}
|
||||
@@ -1421,12 +1654,14 @@ export async function downloadRisuHub(id:string, arg:{
|
||||
}
|
||||
|
||||
if(res.headers.get('content-type') === 'image/png'){
|
||||
let db = getDatabase()
|
||||
await importCharacterProcess({
|
||||
name: 'realm.png',
|
||||
data: res.body
|
||||
data: res.body,
|
||||
lightningRealmImport: db.lightningRealmImport
|
||||
})
|
||||
checkCharOrder()
|
||||
let db = get(DataBase)
|
||||
db = getDatabase()
|
||||
if(db.characters[db.characters.length-1] && (db.goCharacterOnImport || arg.forceRedirect)){
|
||||
const index = db.characters.length-1
|
||||
characterFormatUpdate(index);
|
||||
@@ -1443,7 +1678,7 @@ export async function downloadRisuHub(id:string, arg:{
|
||||
|
||||
await importCharacterCardSpec(data, await getHubResources(img), 'hub')
|
||||
checkCharOrder()
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(db.characters[db.characters.length-1] && (db.goCharacterOnImport || arg.forceRedirect)){
|
||||
const index = db.characters.length-1
|
||||
characterFormatUpdate(index);
|
||||
@@ -1580,6 +1815,7 @@ interface charBookEntry{
|
||||
constant?: boolean // if true, always inserted in the prompt (within budget limit)
|
||||
position?: 'before_char' | 'after_char' // whether the entry is placed before or after the character defs
|
||||
case_sensitive?:boolean
|
||||
use_regex?:boolean
|
||||
}
|
||||
|
||||
interface RccCardMetaData{
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { get, writable } from "svelte/store";
|
||||
import { DataBase, saveImage, setDatabase, type character, type Chat, defaultSdDataFunc, type loreBook } from "./storage/database";
|
||||
import { saveImage, setDatabase, type character, type Chat, defaultSdDataFunc, type loreBook, getDatabase, getCharacterByIndex, setCharacterByIndex } from "./storage/database.svelte";
|
||||
import { alertAddCharacter, alertConfirm, alertError, alertNormal, alertSelect, alertStore, alertWait } from "./alert";
|
||||
import { language } from "../lang";
|
||||
import { decode as decodeMsgpack } from "msgpackr";
|
||||
import { checkNullish, findCharacterbyId, getUserName, selectMultipleFile, selectSingleFile, sleep } from "./util";
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { MobileGUIStack, OpenRealmStore, selectedCharID } from "./stores";
|
||||
import { checkCharOrder, downloadFile, getFileSrc } from "./storage/globalApi";
|
||||
import { MobileGUIStack, OpenRealmStore, selectedCharID } from "./stores.svelte";
|
||||
import { checkCharOrder, downloadFile, getFileSrc } from "./globalApi.svelte";
|
||||
import { reencodeImage } from "./process/files/image";
|
||||
import { updateInlayScreen } from "./process/inlayScreen";
|
||||
import { PngChunk } from "./pngChunk";
|
||||
import { parseMarkdownSafe } from "./parser";
|
||||
import { parseMarkdownSafe } from "./parser.svelte";
|
||||
import { translateHTML } from "./translator/translator";
|
||||
import { doingChat } from "./process";
|
||||
import { doingChat } from "./process/index.svelte";
|
||||
import { importCharacter } from "./characterCards";
|
||||
|
||||
export function createNewCharacter() {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
db.characters.push(createBlankChar())
|
||||
setDatabase(db)
|
||||
checkCharOrder()
|
||||
@@ -24,7 +24,7 @@ export function createNewCharacter() {
|
||||
}
|
||||
|
||||
export function createNewGroup(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
db.characters.push({
|
||||
type: 'group',
|
||||
name: "",
|
||||
@@ -45,7 +45,8 @@ export function createNewGroup(){
|
||||
chaId: uuidv4(),
|
||||
firstMsgIndex: -1,
|
||||
characterTalks: [],
|
||||
characterActive: []
|
||||
characterActive: [],
|
||||
realmId: ''
|
||||
})
|
||||
setDatabase(db)
|
||||
checkCharOrder()
|
||||
@@ -82,7 +83,7 @@ export async function selectCharImg(charIndex:number) {
|
||||
return
|
||||
}
|
||||
const img = selected.data
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const imgp = await saveImage(await reencodeImage(img))
|
||||
dumpCharImage(charIndex)
|
||||
db.characters[charIndex].image = imgp
|
||||
@@ -90,7 +91,7 @@ export async function selectCharImg(charIndex:number) {
|
||||
}
|
||||
|
||||
export function dumpCharImage(charIndex:number) {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const char = db.characters[charIndex] as character
|
||||
if(!char.image || char.image === ''){
|
||||
return
|
||||
@@ -108,7 +109,7 @@ export function dumpCharImage(charIndex:number) {
|
||||
}
|
||||
|
||||
export function changeCharImage(charIndex:number,changeIndex:number) {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const char = db.characters[charIndex] as character
|
||||
const image = char.ccAssets[changeIndex].uri
|
||||
char.ccAssets.splice(changeIndex, 1)
|
||||
@@ -128,7 +129,7 @@ export async function addCharEmotion(charId:number) {
|
||||
addingEmotion.set(false)
|
||||
return
|
||||
}
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
for(const f of selected){
|
||||
const img = f.data
|
||||
const imgp = await saveImage(img)
|
||||
@@ -144,7 +145,7 @@ export async function addCharEmotion(charId:number) {
|
||||
}
|
||||
|
||||
export async function rmCharEmotion(charId:number, emotionId:number) {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let dbChar = db.characters[charId]
|
||||
if(dbChar.type !== 'group'){
|
||||
dbChar.emotionImages.splice(emotionId, 1)
|
||||
@@ -161,7 +162,7 @@ export async function exportChat(page:number){
|
||||
const doTranslate = (mode === '2' || mode === '3') ? (await alertSelect([language.translateContent, language.doNotTranslate])) === '0' : false
|
||||
const anonymous = (mode === '2' || mode === '3') ? ((await alertSelect([language.includePersonaName, language.hidePersonaName])) === '1') : false
|
||||
const selectedID = get(selectedCharID)
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const chat = db.characters[selectedID].chats[page]
|
||||
const char = db.characters[selectedID]
|
||||
const date = new Date().toJSON();
|
||||
@@ -335,7 +336,7 @@ export async function importChat(){
|
||||
}
|
||||
try {
|
||||
const selectedID = get(selectedCharID)
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
|
||||
if(dat.name.endsWith('jsonl')){
|
||||
const lines = Buffer.from(dat.data).toString('utf-8').split('\n')
|
||||
@@ -412,15 +413,14 @@ export async function importChat(){
|
||||
}
|
||||
|
||||
function formatTavernChat(chat:string, charName:string){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
return chat.replace(/<([Uu]ser)>|\{\{([Uu]ser)\}\}/g, getUserName()).replace(/((\{\{)|<)([Cc]har)(=.+)?((\}\})|>)/g, charName)
|
||||
}
|
||||
|
||||
export function characterFormatUpdate(index:number|character, arg:{
|
||||
export function characterFormatUpdate(indexOrCharacter:number|character, arg:{
|
||||
updateInteraction?:boolean,
|
||||
} = {}){
|
||||
let db = get(DataBase)
|
||||
let cha = typeof(index) === 'number' ? db.characters[index] : index
|
||||
let cha = typeof(indexOrCharacter) === 'number' ? getCharacterByIndex(indexOrCharacter) : indexOrCharacter
|
||||
if(cha.chats.length === 0){
|
||||
cha.chats = [{
|
||||
message: [],
|
||||
@@ -511,9 +511,8 @@ export function characterFormatUpdate(index:number|character, arg:{
|
||||
cha.customscript = []
|
||||
}
|
||||
cha.lastInteraction = Date.now()
|
||||
if(typeof(index) === 'number'){
|
||||
db.characters[index] = cha
|
||||
setDatabase(db)
|
||||
if(typeof(indexOrCharacter) === 'number'){
|
||||
setCharacterByIndex(indexOrCharacter, cha)
|
||||
}
|
||||
cha.chats = cha.chats.map((v) => {
|
||||
v.fmIndex ??= cha.firstMsgIndex ?? -1
|
||||
@@ -587,7 +586,7 @@ export async function makeGroupImage() {
|
||||
type: 'wait',
|
||||
msg: `Loading..`
|
||||
})
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const charID = get(selectedCharID)
|
||||
const group = db.characters[charID]
|
||||
if(group.type !== 'group'){
|
||||
@@ -687,7 +686,7 @@ export async function addDefaultCharacters() {
|
||||
return
|
||||
}
|
||||
let char:character = va.data
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(char.emotionImages && char.emotionImages.length > 0){
|
||||
for(let i=0;i<char.emotionImages.length;i++){
|
||||
await sleep(10)
|
||||
@@ -720,7 +719,7 @@ export async function addDefaultCharacters() {
|
||||
}
|
||||
|
||||
export async function removeChar(index:number,name:string, type:'normal'|'permanent'|'permanentForce' = 'normal'){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(type !== 'permanentForce'){
|
||||
const conf = await alertConfirm(language.removeConfirm + name)
|
||||
if(!conf){
|
||||
@@ -771,7 +770,7 @@ export async function addCharacter(arg:{
|
||||
MobileGUIStack.set(1)
|
||||
return
|
||||
}
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(db.characters[db.characters.length-1]){
|
||||
changeChar(db.characters.length-1)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { language } from "src/lang";
|
||||
import { alertError, alertInput, alertNormal, alertSelect, alertStore } from "../alert";
|
||||
import { requestChatData } from "../process/request";
|
||||
import { checkCharOrder, globalFetch, isNodeServer, isTauri, saveAsset } from "../storage/globalApi";
|
||||
import { checkCharOrder, globalFetch, isNodeServer, isTauri, saveAsset } from "../globalApi.svelte";
|
||||
import { tokenize } from "../tokenizer";
|
||||
import { createBlankChar } from "../characters";
|
||||
import { DataBase, setDatabase, type character } from "../storage/database";
|
||||
import { get } from "svelte/store";
|
||||
import { getDatabase, setDatabase, type character } from "../storage/database.svelte";
|
||||
import { sleep } from "../util";
|
||||
import { Capacitor } from "@capacitor/core";
|
||||
|
||||
@@ -306,7 +305,7 @@ async function createBotFromWeb() {
|
||||
})
|
||||
const d = (sel === 0) ? (await createBotFromWebMain(search)) : (await createBotByAI(search))
|
||||
if(d.ok === 'creation'){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const cha = d.data
|
||||
const fm = await createFirstMsg(cha.desc)
|
||||
if(fm.type === 'multiline' || fm.type === 'fail' || fm.type === 'streaming'){
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { get } from "svelte/store"
|
||||
import { hubURL } from "../characterCards"
|
||||
import { DataBase } from "../storage/database"
|
||||
import { getDatabase } from "../storage/database.svelte"
|
||||
import { alertError, alertSelect } from "../alert"
|
||||
|
||||
export async function risuLogin() {
|
||||
@@ -14,7 +13,7 @@ export async function risuLogin() {
|
||||
}
|
||||
|
||||
export async function saveRisuAccountData() {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(!db.account){
|
||||
alertError("Not logged in error")
|
||||
return
|
||||
@@ -33,7 +32,7 @@ export async function saveRisuAccountData() {
|
||||
}
|
||||
|
||||
export async function loadRisuAccountData() {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(!db.account){
|
||||
alertError("Not logged in error")
|
||||
return
|
||||
@@ -52,7 +51,7 @@ export async function loadRisuAccountData() {
|
||||
}
|
||||
|
||||
export async function loadRisuAccountBackup() {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(!db.account){
|
||||
alertError("Not logged in error")
|
||||
return
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { BaseDirectory, readBinaryFile, readDir, writeBinaryFile } from "@tauri-apps/api/fs";
|
||||
import { BaseDirectory, readFile, readDir, writeFile } from "@tauri-apps/plugin-fs";
|
||||
import { alertError, alertNormal, alertStore, alertWait } from "../alert";
|
||||
import { LocalWriter, forageStorage, isTauri } from "../storage/globalApi";
|
||||
import { decodeRisuSave, encodeRisuSave } from "../storage/risuSave";
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase } from "../storage/database";
|
||||
import { save } from "@tauri-apps/api/dialog";
|
||||
import { relaunch } from "@tauri-apps/api/process";
|
||||
import { LocalWriter, forageStorage, isTauri } from "../globalApi.svelte";
|
||||
import { decodeRisuSave, encodeRisuSaveLegacy } from "../storage/risuSave";
|
||||
import { getDatabase, setDatabaseLite } from "../storage/database.svelte";
|
||||
import { relaunch } from "@tauri-apps/plugin-process";
|
||||
import { sleep } from "../util";
|
||||
import { hubURL } from "../characterCards";
|
||||
|
||||
@@ -32,7 +30,7 @@ export async function SaveLocalBackup(){
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(get(DataBase)),
|
||||
body: JSON.stringify(getDatabase()),
|
||||
})
|
||||
if(corrupted.status === 400){
|
||||
alertError('Failed, Backup data is corrupted')
|
||||
@@ -41,7 +39,7 @@ export async function SaveLocalBackup(){
|
||||
|
||||
|
||||
if(isTauri){
|
||||
const assets = await readDir('assets', {dir: BaseDirectory.AppData})
|
||||
const assets = await readDir('assets', {baseDir: BaseDirectory.AppData})
|
||||
let i = 0;
|
||||
for(let asset of assets){
|
||||
i += 1;
|
||||
@@ -50,7 +48,7 @@ export async function SaveLocalBackup(){
|
||||
if(!key || !key.endsWith('.png')){
|
||||
continue
|
||||
}
|
||||
await writer.writeBackup(key, await readBinaryFile(asset.path))
|
||||
await writer.writeBackup(key, await readFile('assets/' + asset.name, {baseDir: BaseDirectory.AppData}))
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -63,14 +61,14 @@ export async function SaveLocalBackup(){
|
||||
if(!key || !key.endsWith('.png')){
|
||||
continue
|
||||
}
|
||||
await writer.writeBackup(key, await forageStorage.getItem(key))
|
||||
await writer.writeBackup(key, await forageStorage.getItem(key) as unknown as Uint8Array)
|
||||
if(forageStorage.isAccount){
|
||||
await sleep(1000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dbData = encodeRisuSave(get(DataBase), 'compression')
|
||||
const dbData = encodeRisuSaveLegacy(getDatabase(), 'compression')
|
||||
|
||||
alertWait(`Saving local Backup... (Saving database)`)
|
||||
|
||||
@@ -113,9 +111,9 @@ export async function LoadLocalBackup(){
|
||||
if(name === 'database.risudat'){
|
||||
const db = new Uint8Array(data)
|
||||
const dbData = await decodeRisuSave(db)
|
||||
DataBase.set(dbData)
|
||||
setDatabaseLite(dbData)
|
||||
if(isTauri){
|
||||
await writeBinaryFile('database/database.bin', db, {dir: BaseDirectory.AppData})
|
||||
await writeFile('database/database.bin', db, {baseDir: BaseDirectory.AppData})
|
||||
relaunch()
|
||||
alertStore.set({
|
||||
type: "wait",
|
||||
@@ -133,7 +131,7 @@ export async function LoadLocalBackup(){
|
||||
continue
|
||||
}
|
||||
if(isTauri){
|
||||
await writeBinaryFile(`assets/` + name, data ,{dir: BaseDirectory.AppData})
|
||||
await writeFile(`assets/` + name, data ,{baseDir: BaseDirectory.AppData})
|
||||
}
|
||||
else{
|
||||
await forageStorage.setItem('assets/' + name, data)
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { get } from "svelte/store";
|
||||
import { alertError, alertErrorWait, alertInput, alertNormal, alertSelect, alertStore } from "../alert";
|
||||
import { DataBase, setDatabase, type Database } from "../storage/database";
|
||||
import { forageStorage, getUnpargeables, isNodeServer, isTauri, openURL } from "../storage/globalApi";
|
||||
import { BaseDirectory, exists, readBinaryFile, readDir, writeBinaryFile } from "@tauri-apps/api/fs";
|
||||
import { alertError, alertInput, alertNormal, alertSelect, alertStore } from "../alert";
|
||||
import { getDatabase, type Database } from "../storage/database.svelte";
|
||||
import { forageStorage, getUnpargeables, isTauri, openURL } from "../globalApi.svelte";
|
||||
import { BaseDirectory, exists, readFile, readDir, writeFile } from "@tauri-apps/plugin-fs";
|
||||
import { language } from "../../lang";
|
||||
import { relaunch } from '@tauri-apps/api/process';
|
||||
import { isEqual } from "lodash";
|
||||
import { relaunch } from '@tauri-apps/plugin-process';
|
||||
import { sleep } from "../util";
|
||||
import { hubURL } from "../characterCards";
|
||||
import { decodeRisuSave, encodeRisuSave } from "../storage/risuSave";
|
||||
import { decodeRisuSave, encodeRisuSaveLegacy } from "../storage/risuSave";
|
||||
|
||||
export async function checkDriver(type:'save'|'load'|'loadtauri'|'savetauri'|'reftoken'){
|
||||
const CLIENT_ID = '580075990041-l26k2d3c0nemmqiu3d3aag01npfrkn76.apps.googleusercontent.com';
|
||||
@@ -110,91 +108,8 @@ let BackupDb:Database = null
|
||||
|
||||
|
||||
export async function syncDrive() {
|
||||
BackupDb = structuredClone(get(DataBase))
|
||||
BackupDb = safeStructuredClone(getDatabase())
|
||||
return
|
||||
while(true){
|
||||
const maindb = get(DataBase)
|
||||
if(maindb?.account?.data?.access_token && maindb?.account?.data?.refresh_token && maindb?.account?.data?.expires_in){
|
||||
if(maindb.account.data.expires_in < Date.now()){
|
||||
if(!maindb.account){
|
||||
alertError("Not logged in error")
|
||||
return
|
||||
}
|
||||
const s = await fetch(hubURL + '/drive/refresh', {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
token: maindb.account.token
|
||||
})
|
||||
})
|
||||
if(s.status !== 200){
|
||||
alertError(await s.text())
|
||||
return
|
||||
}
|
||||
maindb.account.data = await s.json()
|
||||
}
|
||||
const ACCESS_TOKEN = maindb.account.data.access_token
|
||||
const d = await loadDrive(ACCESS_TOKEN, 'sync')
|
||||
lastSaved = Math.floor(Date.now() / 1000)
|
||||
localStorage.setItem('risu_lastsaved', `${lastSaved}`)
|
||||
const hadNoSync = d === 'noSync'
|
||||
if((!isEqual(maindb, BackupDb)) || hadNoSync){
|
||||
BackupDb = structuredClone(maindb)
|
||||
const files:DriveFile[] = await getFilesInFolder(ACCESS_TOKEN)
|
||||
const fileNames = files.map((d) => {
|
||||
return d.name
|
||||
})
|
||||
if(isTauri){
|
||||
const assets = await readDir('assets', {dir: BaseDirectory.AppData})
|
||||
let i = 0;
|
||||
for(let asset of assets){
|
||||
i += 1;
|
||||
if(hadNoSync){
|
||||
alertStore.set({
|
||||
type: "wait",
|
||||
msg: `Uploading Sync Files... (${i} / ${assets.length})`
|
||||
})
|
||||
}
|
||||
const key = asset.name
|
||||
if(!key || !key.endsWith('.png')){
|
||||
continue
|
||||
}
|
||||
const formatedKey = formatKeys(key)
|
||||
if(!fileNames.includes(formatedKey)){
|
||||
await createFileInFolder(ACCESS_TOKEN, formatedKey, await readBinaryFile(asset.path))
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
const keys = await forageStorage.keys()
|
||||
|
||||
for(let i=0;i<keys.length;i++){
|
||||
if(hadNoSync){
|
||||
alertStore.set({
|
||||
type: "wait",
|
||||
msg: `Uploading Sync Files... (${i} / ${keys.length})`
|
||||
})
|
||||
}
|
||||
const key = keys[i]
|
||||
if(!key.endsWith('.png')){
|
||||
continue
|
||||
}
|
||||
const formatedKey = formatKeys(key)
|
||||
if(!fileNames.includes(formatedKey)){
|
||||
await createFileInFolder(ACCESS_TOKEN, formatedKey, await forageStorage.getItem(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
const dbjson = JSON.stringify(get(DataBase))
|
||||
lastSaved = Math.floor(Date.now() / 1000)
|
||||
localStorage.setItem('risu_lastsaved', `${lastSaved}`)
|
||||
await createFileInFolder(ACCESS_TOKEN, `${lastSaved}-database.risudat2`, Buffer.from(dbjson, 'utf-8'))
|
||||
if(hadNoSync){
|
||||
alertNormal("First Setup Success")
|
||||
}
|
||||
}
|
||||
}
|
||||
await sleep(3000)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +125,7 @@ async function backupDrive(ACCESS_TOKEN:string) {
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(get(DataBase)),
|
||||
body: JSON.stringify(getDatabase()),
|
||||
})
|
||||
if(corrupted.status === 400){
|
||||
alertError('Failed, Backup data is corrupted')
|
||||
@@ -224,7 +139,7 @@ async function backupDrive(ACCESS_TOKEN:string) {
|
||||
})
|
||||
|
||||
if(isTauri){
|
||||
const assets = await readDir('assets', {dir: BaseDirectory.AppData})
|
||||
const assets = await readDir('assets', {baseDir: BaseDirectory.AppData})
|
||||
let i = 0;
|
||||
for(let asset of assets){
|
||||
i += 1;
|
||||
@@ -238,7 +153,7 @@ async function backupDrive(ACCESS_TOKEN:string) {
|
||||
}
|
||||
const formatedKey = newFormatKeys(key)
|
||||
if(!fileNames.includes(formatedKey)){
|
||||
await createFileInFolder(ACCESS_TOKEN, formatedKey, await readBinaryFile(asset.path))
|
||||
await createFileInFolder(ACCESS_TOKEN, formatedKey, await readFile('assets/' + asset.name, {baseDir: BaseDirectory.AppData}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,12 +171,12 @@ async function backupDrive(ACCESS_TOKEN:string) {
|
||||
}
|
||||
const formatedKey = newFormatKeys(key)
|
||||
if(!fileNames.includes(formatedKey)){
|
||||
await createFileInFolder(ACCESS_TOKEN, formatedKey, await forageStorage.getItem(key))
|
||||
await createFileInFolder(ACCESS_TOKEN, formatedKey, await forageStorage.getItem(key) as unknown as Uint8Array)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dbData = encodeRisuSave(get(DataBase), 'compression')
|
||||
const dbData = encodeRisuSaveLegacy(getDatabase(), 'compression')
|
||||
|
||||
alertStore.set({
|
||||
type: "wait",
|
||||
@@ -290,14 +205,14 @@ async function loadDrive(ACCESS_TOKEN:string, mode: 'backup'|'sync'):Promise<voi
|
||||
const files:DriveFile[] = await getFilesInFolder(ACCESS_TOKEN)
|
||||
let foragekeys:string[] = []
|
||||
let loadedForageKeys = false
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
|
||||
async function checkImageExists(images:string) {
|
||||
if(db?.account?.useSync){
|
||||
return false
|
||||
}
|
||||
if(isTauri){
|
||||
return await exists(`assets/` + images, {dir: BaseDirectory.AppData})
|
||||
return await exists(`assets/` + images, {baseDir: BaseDirectory.AppData})
|
||||
}
|
||||
else{
|
||||
if(!loadedForageKeys){
|
||||
@@ -372,7 +287,7 @@ async function loadDrive(ACCESS_TOKEN:string, mode: 'backup'|'sync'):Promise<voi
|
||||
}
|
||||
const selectedIndex = (await alertSelect([language.loadLatest, language.loadOthers]) === '0') ? 0 : parseInt(await alertSelect(selectables))
|
||||
const selectedDb = dbs[selectedIndex][0]
|
||||
const decompressedDb:Database = decodeRisuSave(await getFileData(ACCESS_TOKEN, selectedDb.id))
|
||||
const decompressedDb:Database = await decodeRisuSave(await getFileData(ACCESS_TOKEN, selectedDb.id))
|
||||
return decompressedDb
|
||||
}
|
||||
|
||||
@@ -408,7 +323,7 @@ async function loadDrive(ACCESS_TOKEN:string, mode: 'backup'|'sync'):Promise<voi
|
||||
if(file.name === formatedImage){
|
||||
const fData = await getFileData(ACCESS_TOKEN, file.id)
|
||||
if(isTauri){
|
||||
await writeBinaryFile(`assets/` + images, fData ,{dir: BaseDirectory.AppData})
|
||||
await writeFile(`assets/` + images, fData ,{baseDir: BaseDirectory.AppData})
|
||||
|
||||
}
|
||||
else{
|
||||
@@ -430,10 +345,10 @@ async function loadDrive(ACCESS_TOKEN:string, mode: 'backup'|'sync'):Promise<voi
|
||||
}
|
||||
}
|
||||
db.didFirstSetup = true
|
||||
const dbData = encodeRisuSave(db, 'compression')
|
||||
const dbData = encodeRisuSaveLegacy(db, 'compression')
|
||||
|
||||
if(isTauri){
|
||||
await writeBinaryFile('database/database.bin', dbData, {dir: BaseDirectory.AppData})
|
||||
await writeFile('database/database.bin', dbData, {baseDir: BaseDirectory.AppData})
|
||||
relaunch()
|
||||
alertStore.set({
|
||||
type: "wait",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase } from "../storage/database";
|
||||
import { getDatabase } from "../storage/database.svelte";
|
||||
|
||||
export function updateAnimationSpeed(){
|
||||
const db = get(DataBase);
|
||||
const db = getDatabase();
|
||||
document.documentElement.style.setProperty('--risu-animation-speed', db.animationSpeed + 's');
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
import { get, writable } from "svelte/store";
|
||||
import { DataBase, setDatabase } from "../storage/database";
|
||||
import { downloadFile } from "../storage/globalApi";
|
||||
import { getDatabase, setDatabase } from "../storage/database.svelte";
|
||||
import { downloadFile } from "../globalApi.svelte";
|
||||
import { BufferToText, selectSingleFile } from "../util";
|
||||
import { alertError } from "../alert";
|
||||
import { isLite } from "../lite";
|
||||
import { CustomCSSStore, SafeModeStore } from "../stores";
|
||||
import { CustomCSSStore, SafeModeStore } from "../stores.svelte";
|
||||
|
||||
export interface ColorScheme{
|
||||
bgcolor: string;
|
||||
@@ -94,6 +94,18 @@ const colorShemes = {
|
||||
darkBorderc: "#4b5563",
|
||||
darkbutton: "#374151",
|
||||
type:'dark'
|
||||
},
|
||||
"lite": {
|
||||
bgcolor: "#1f2937",
|
||||
darkbg: "#1C2533",
|
||||
borderc: "#475569",
|
||||
selected: "#475569",
|
||||
draculared: "#ff5555",
|
||||
textcolor: "#f8f8f2",
|
||||
textcolor2: "#64748b",
|
||||
darkBorderc: "#030712",
|
||||
darkbutton: "#374151",
|
||||
type:'dark'
|
||||
}
|
||||
|
||||
} as const
|
||||
@@ -103,9 +115,9 @@ export const ColorSchemeTypeStore = writable('dark' as 'dark'|'light')
|
||||
export const colorSchemeList = Object.keys(colorShemes) as (keyof typeof colorShemes)[]
|
||||
|
||||
export function changeColorScheme(colorScheme: string){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(colorScheme !== 'custom'){
|
||||
db.colorScheme = structuredClone(colorShemes[colorScheme])
|
||||
db.colorScheme = safeStructuredClone(colorShemes[colorScheme])
|
||||
}
|
||||
db.colorSchemeName = colorScheme
|
||||
setDatabase(db)
|
||||
@@ -113,16 +125,16 @@ export function changeColorScheme(colorScheme: string){
|
||||
}
|
||||
|
||||
export function updateColorScheme(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
|
||||
let colorScheme = db.colorScheme
|
||||
|
||||
if(colorScheme == null){
|
||||
colorScheme = structuredClone(defaultColorScheme)
|
||||
colorScheme = safeStructuredClone(defaultColorScheme)
|
||||
}
|
||||
|
||||
if(get(isLite)){
|
||||
colorScheme = structuredClone(colorShemes.light)
|
||||
colorScheme = safeStructuredClone(colorShemes.lite)
|
||||
}
|
||||
|
||||
//set css variables
|
||||
@@ -139,7 +151,7 @@ export function updateColorScheme(){
|
||||
}
|
||||
|
||||
export function exportColorScheme(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let json = JSON.stringify(db.colorScheme)
|
||||
downloadFile('colorScheme.json', json)
|
||||
}
|
||||
@@ -169,7 +181,7 @@ export async function importColorScheme(){
|
||||
return
|
||||
}
|
||||
changeColorScheme('custom')
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
db.colorScheme = colorScheme
|
||||
setDatabase(db)
|
||||
updateColorScheme()
|
||||
@@ -182,13 +194,13 @@ export async function importColorScheme(){
|
||||
}
|
||||
|
||||
export function updateTextThemeAndCSS(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const root = document.querySelector(':root') as HTMLElement;
|
||||
if(!root){
|
||||
return
|
||||
}
|
||||
let textTheme = get(isLite) ? 'standard' : db.textTheme
|
||||
let colorScheme = get(isLite) ? 'light' : db.colorScheme.type
|
||||
let colorScheme = get(isLite) ? 'dark' : db.colorScheme.type
|
||||
switch(textTheme){
|
||||
case "standard":{
|
||||
if(colorScheme === 'dark'){
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { get, writable } from "svelte/store";
|
||||
import { DataBase } from "../storage/database";
|
||||
import { writable } from "svelte/store";
|
||||
import { getDatabase } from "../storage/database.svelte";
|
||||
|
||||
export let textAreaSize = writable(0)
|
||||
export let sideBarSize = writable(0)
|
||||
export let textAreaTextSize = writable(0)
|
||||
|
||||
export function updateGuisize(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const root = document.querySelector(':root') as HTMLElement;
|
||||
if(!root){
|
||||
return
|
||||
|
||||
@@ -126,10 +126,10 @@ const deprecatedCBSwithParams = [
|
||||
'remaind', 'pow'
|
||||
]
|
||||
|
||||
const decorators = [
|
||||
export const decorators = [
|
||||
'activate_only_after', 'activate_only_every', 'keep_activate_after_match', 'dont_activate_after_match', 'depth', 'reverse_depth',
|
||||
'instruct_depth', 'reverse_instruct_depth', 'instruct_scan_depth', 'role', 'scan_depth', 'is_greeting', 'position', 'ignore_on_max_context',
|
||||
'additional_keys', 'exclude_keys', 'is_user_icon', 'activate', 'dont_activate', 'disable_ui_prompt', 'probability'
|
||||
'additional_keys', 'exclude_keys', 'is_user_icon', 'activate', 'dont_activate', 'disable_ui_prompt', 'probability', 'exclude_keys_all', 'match_full_word', 'match_partial_word'
|
||||
]
|
||||
|
||||
const deprecatedDecorators = [
|
||||
|
||||
@@ -1,13 +1,62 @@
|
||||
import { get } from "svelte/store"
|
||||
import { alertSelect, alertToast, doingAlert } from "./alert"
|
||||
import { DataBase, changeToPreset as changeToPreset2 } from "./storage/database"
|
||||
import { MobileGUIStack, MobileSideBar, openPersonaList, openPresetList, SafeModeStore, selectedCharID, settingsOpen } from "./stores"
|
||||
import { changeToPreset as changeToPreset2, getDatabase } from "./storage/database.svelte"
|
||||
import { alertStore, MobileGUIStack, MobileSideBar, openPersonaList, openPresetList, SafeModeStore, selectedCharID, settingsOpen } from "./stores.svelte"
|
||||
import { language } from "src/lang"
|
||||
import { updateTextThemeAndCSS } from "./gui/colorscheme"
|
||||
|
||||
export function initHotkey(){
|
||||
document.addEventListener('keydown', (ev) => {
|
||||
if(ev.ctrlKey){
|
||||
|
||||
if(ev.altKey){
|
||||
switch(ev.key){
|
||||
case "r":{
|
||||
ev.preventDefault()
|
||||
clickQuery('.button-icon-reroll')
|
||||
return
|
||||
}
|
||||
case "f":{
|
||||
ev.preventDefault()
|
||||
clickQuery('.button-icon-unreroll')
|
||||
return
|
||||
}
|
||||
case "t":{
|
||||
ev.preventDefault()
|
||||
clickQuery('.button-icon-translate')
|
||||
return
|
||||
}
|
||||
case "d":{
|
||||
ev.preventDefault()
|
||||
clickQuery('.button-icon-remove')
|
||||
return
|
||||
}
|
||||
case 'e':{
|
||||
ev.preventDefault()
|
||||
clickQuery('.button-icon-edit')
|
||||
setTimeout(() => {
|
||||
focusQuery('.message-edit-area')
|
||||
}, 100)
|
||||
return
|
||||
}
|
||||
case 'c':{
|
||||
ev.preventDefault()
|
||||
clickQuery('.button-icon-copy')
|
||||
return
|
||||
}
|
||||
case 'i':{
|
||||
ev.preventDefault()
|
||||
focusQuery('.text-input-area')
|
||||
return
|
||||
}
|
||||
case 'Enter':{
|
||||
ev.preventDefault()
|
||||
clickQuery('.button-icon-send')
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (ev.key){
|
||||
case "1":{
|
||||
changeToPreset(0)
|
||||
@@ -105,6 +154,15 @@ export function initHotkey(){
|
||||
}
|
||||
ev.preventDefault()
|
||||
}
|
||||
if(ev.key === 'Enter'){
|
||||
const alertType = get(alertStore).type
|
||||
if(alertType === 'ask' || alertType === 'normal' || alertType === 'error'){
|
||||
alertStore.set({
|
||||
type: 'none',
|
||||
msg: 'yes'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -143,6 +201,23 @@ export function initHotkey(){
|
||||
})
|
||||
}
|
||||
|
||||
function clickQuery(query:string){
|
||||
let ele = document.querySelector(query) as HTMLElement
|
||||
console.log(ele)
|
||||
if(ele){
|
||||
ele.click()
|
||||
}
|
||||
}
|
||||
|
||||
function focusQuery(query:string){
|
||||
let ele = document.querySelector(query) as HTMLElement
|
||||
if(ele){
|
||||
ele.focus()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function initMobileGesture(){
|
||||
|
||||
let pressingPointers = new Map<number, {x:number, y:number}>()
|
||||
@@ -197,7 +272,7 @@ export function initMobileGesture(){
|
||||
|
||||
function changeToPreset(num:number){
|
||||
if(!doingAlert()){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let pres = db.botPresets
|
||||
if(pres.length > num){
|
||||
alertToast(`Changed to Preset: ${pres[num].name}`)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { get } from "svelte/store"
|
||||
import { alertNormal, alertSelect } from "../alert"
|
||||
import { keiServerURL } from "./kei"
|
||||
import { DataBase, setDatabase } from "../storage/database"
|
||||
import { getDatabase, setDatabase } from "../storage/database.svelte"
|
||||
|
||||
export async function autoServerBackup(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const res = await fetch(keiServerURL() + '/autobackup/list', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -81,7 +80,7 @@ export async function autoServerBackup(){
|
||||
let lastKeiSave = 0
|
||||
export async function saveDbKei() {
|
||||
try{
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(db.account.kei){
|
||||
if(Date.now() - lastKeiSave < 60000 * 5){
|
||||
return
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { get } from "svelte/store";
|
||||
import { hubURL } from "../characterCards";
|
||||
import { DataBase } from "../storage/database";
|
||||
import { getDatabase } from "../storage/database.svelte";
|
||||
|
||||
export function keiServerURL(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(db.keiServerURL) return db.keiServerURL;
|
||||
return hubURL + "/kei";
|
||||
}
|
||||
754
src/ts/loggen.ts
Normal file
754
src/ts/loggen.ts
Normal file
@@ -0,0 +1,754 @@
|
||||
// Log Generator by dootaang, GPL3
|
||||
// Typescript version by Kwaroran
|
||||
|
||||
|
||||
interface templateStyles{
|
||||
gradientModern:boolean,
|
||||
showBotName:boolean,
|
||||
botName:string,
|
||||
showTags:boolean,
|
||||
tagLayout:{
|
||||
content:string,
|
||||
border_radius:number,
|
||||
font_size:number,
|
||||
padding:{
|
||||
top:number,
|
||||
right:number,
|
||||
bottom:number,
|
||||
left:number
|
||||
},
|
||||
text_color:string,
|
||||
style:string,
|
||||
color:string
|
||||
|
||||
}[]
|
||||
showProfile:boolean,
|
||||
showProfileImage:boolean,
|
||||
widthInput:number,
|
||||
heightInput:number,
|
||||
frameStyle:string,
|
||||
outerBoxColor:string,
|
||||
innerBoxColor:string,
|
||||
shadowIntensity:number,
|
||||
useBoxBorder:boolean,
|
||||
boxBorderColor:string,
|
||||
boxBorderThickness:number,
|
||||
showInnerBox:boolean,
|
||||
profileBorderColor:string,
|
||||
showProfileShadow:boolean,
|
||||
showProfileBorder:boolean,
|
||||
botNameColor:string,
|
||||
showDivider:boolean,
|
||||
dividerThickness:number,
|
||||
dividerStyle:string,
|
||||
dividerOuterColor:string,
|
||||
dividerInnerColor:string,
|
||||
dividerSolidColor:string,
|
||||
styles:{
|
||||
font_family:string,
|
||||
text:string,
|
||||
font_size_normal:number,
|
||||
font_weight_bold:number,
|
||||
radius_normal:number,
|
||||
radius_large:number,
|
||||
spacing_large:number
|
||||
}
|
||||
}
|
||||
|
||||
interface LogGenTemplate{
|
||||
name:string,
|
||||
theme:{
|
||||
colors:{
|
||||
outer_box:string,
|
||||
inner_box:string,
|
||||
background:string,
|
||||
bot_name:string,
|
||||
dialog:string,
|
||||
narration:string,
|
||||
inner_thoughts:string,
|
||||
profile_border:string,
|
||||
box_border:string,
|
||||
image_border:string,
|
||||
divider_outer:string,
|
||||
divider_inner:string,
|
||||
gradient_start:string,
|
||||
gradient_end:string,
|
||||
tag_bg?:string,
|
||||
tag_text?:string
|
||||
},
|
||||
tags:{
|
||||
color:string,
|
||||
text_color:string,
|
||||
border_color:string
|
||||
}[]
|
||||
}
|
||||
gradientModern?:boolean,
|
||||
}
|
||||
|
||||
const templates:LogGenTemplate[] = [
|
||||
{
|
||||
"name": "Modern Blue",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#1a202c",
|
||||
"inner_box": "#2d3748",
|
||||
"background": "#2d3748",
|
||||
"bot_name": "#90cdf4",
|
||||
"dialog": "#f7fafc",
|
||||
"narration": "#e2e8f0",
|
||||
"inner_thoughts": "#cbd5e0",
|
||||
"profile_border": "#4a5568",
|
||||
"box_border": "#4a5568",
|
||||
"image_border": "#4a5568",
|
||||
"divider_outer": "#4a5568",
|
||||
"divider_inner": "#2d3748",
|
||||
"gradient_start": "#1a202c",
|
||||
"gradient_end": "#2d3748"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#2c5282", "text_color": "#bee3f8", "border_color": "#2b6cb0"},
|
||||
{"color": "#2b6cb0", "text_color": "#bee3f8", "border_color": "#3182ce"},
|
||||
{"color": "#3182ce", "text_color": "#ffffff", "border_color": "#4299e1"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Dark Mode",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#000000",
|
||||
"inner_box": "#1a1a1a",
|
||||
"background": "#1a1a1a",
|
||||
"bot_name": "#ffffff",
|
||||
"dialog": "#ffffff",
|
||||
"narration": "#e0e0e0",
|
||||
"inner_thoughts": "#c0c0c0",
|
||||
"profile_border": "#333333",
|
||||
"box_border": "#333333",
|
||||
"image_border": "#333333",
|
||||
"divider_outer": "#333333",
|
||||
"divider_inner": "#1a1a1a",
|
||||
"gradient_start": "#000000",
|
||||
"gradient_end": "#1a1a1a"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#262626", "text_color": "#e0e0e0", "border_color": "#333333"},
|
||||
{"color": "#333333", "text_color": "#e0e0e0", "border_color": "#404040"},
|
||||
{"color": "#404040", "text_color": "#ffffff", "border_color": "#4d4d4d"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Rose Gold",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#ffffff",
|
||||
"inner_box": "#fff5f5",
|
||||
"background": "#fff5f5",
|
||||
"bot_name": "#c53030",
|
||||
"dialog": "#2d3748",
|
||||
"narration": "#4a5568",
|
||||
"inner_thoughts": "#718096",
|
||||
"profile_border": "#feb2b2",
|
||||
"box_border": "#fc8181",
|
||||
"image_border": "#feb2b2",
|
||||
"divider_outer": "#fc8181",
|
||||
"divider_inner": "#ffffff",
|
||||
"gradient_start": "#fff5f5",
|
||||
"gradient_end": "#fed7d7"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#fed7d7", "text_color": "#c53030", "border_color": "#feb2b2"},
|
||||
{"color": "#feb2b2", "text_color": "#c53030", "border_color": "#fc8181"},
|
||||
{"color": "#fc8181", "text_color": "#ffffff", "border_color": "#f56565"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Mint Green",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#ffffff",
|
||||
"inner_box": "#f0fff4",
|
||||
"background": "#f0fff4",
|
||||
"bot_name": "#2f855a",
|
||||
"dialog": "#2d3748",
|
||||
"narration": "#4a5568",
|
||||
"inner_thoughts": "#718096",
|
||||
"profile_border": "#9ae6b4",
|
||||
"box_border": "#68d391",
|
||||
"image_border": "#9ae6b4",
|
||||
"divider_outer": "#68d391",
|
||||
"divider_inner": "#ffffff",
|
||||
"gradient_start": "#f0fff4",
|
||||
"gradient_end": "#c6f6d5"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#c6f6d5", "text_color": "#2f855a", "border_color": "#9ae6b4"},
|
||||
{"color": "#9ae6b4", "text_color": "#2f855a", "border_color": "#68d391"},
|
||||
{"color": "#68d391", "text_color": "#ffffff", "border_color": "#48bb78"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Modern Purple",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#ffffff",
|
||||
"inner_box": "#f8f5ff",
|
||||
"background": "#f8f5ff",
|
||||
"bot_name": "#6b46c1",
|
||||
"dialog": "#2d3748",
|
||||
"narration": "#4a5568",
|
||||
"inner_thoughts": "#718096",
|
||||
"profile_border": "#d6bcfa",
|
||||
"box_border": "#b794f4",
|
||||
"image_border": "#d6bcfa",
|
||||
"divider_outer": "#b794f4",
|
||||
"divider_inner": "#ffffff",
|
||||
"gradient_start": "#f8f5ff",
|
||||
"gradient_end": "#e9d8fd"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#e9d8fd", "text_color": "#6b46c1", "border_color": "#d6bcfa"},
|
||||
{"color": "#d6bcfa", "text_color": "#6b46c1", "border_color": "#b794f4"},
|
||||
{"color": "#b794f4", "text_color": "#ffffff", "border_color": "#9f7aea"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Ocean Blue",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#ffffff",
|
||||
"inner_box": "#ebf8ff",
|
||||
"background": "#ebf8ff",
|
||||
"bot_name": "#2c5282",
|
||||
"dialog": "#2d3748",
|
||||
"narration": "#4a5568",
|
||||
"inner_thoughts": "#718096",
|
||||
"profile_border": "#90cdf4",
|
||||
"box_border": "#63b3ed",
|
||||
"image_border": "#90cdf4",
|
||||
"divider_outer": "#63b3ed",
|
||||
"divider_inner": "#ffffff",
|
||||
"gradient_start": "#ebf8ff",
|
||||
"gradient_end": "#bee3f8"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#bee3f8", "text_color": "#2c5282", "border_color": "#90cdf4"},
|
||||
{"color": "#90cdf4", "text_color": "#2c5282", "border_color": "#63b3ed"},
|
||||
{"color": "#63b3ed", "text_color": "#ffffff", "border_color": "#4299e1"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Sunset Orange",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#ffffff",
|
||||
"inner_box": "#fffaf0",
|
||||
"background": "#fffaf0",
|
||||
"bot_name": "#c05621",
|
||||
"dialog": "#2d3748",
|
||||
"narration": "#4a5568",
|
||||
"inner_thoughts": "#718096",
|
||||
"profile_border": "#fbd38d",
|
||||
"box_border": "#f6ad55",
|
||||
"image_border": "#fbd38d",
|
||||
"divider_outer": "#f6ad55",
|
||||
"divider_inner": "#ffffff",
|
||||
"gradient_start": "#fffaf0",
|
||||
"gradient_end": "#feebc8"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#feebc8", "text_color": "#c05621", "border_color": "#fbd38d"},
|
||||
{"color": "#fbd38d", "text_color": "#c05621", "border_color": "#f6ad55"},
|
||||
{"color": "#f6ad55", "text_color": "#ffffff", "border_color": "#ed8936"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Mocha Brown",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#ffffff",
|
||||
"inner_box": "#faf5f1",
|
||||
"background": "#faf5f1",
|
||||
"bot_name": "#7b341e",
|
||||
"dialog": "#2d3748",
|
||||
"narration": "#4a5568",
|
||||
"inner_thoughts": "#718096",
|
||||
"profile_border": "#d6bcab",
|
||||
"box_border": "#b08b6e",
|
||||
"image_border": "#d6bcab",
|
||||
"divider_outer": "#b08b6e",
|
||||
"divider_inner": "#ffffff",
|
||||
"gradient_start": "#faf5f1",
|
||||
"gradient_end": "#e8d6cf"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#e8d6cf", "text_color": "#7b341e", "border_color": "#d6bcab"},
|
||||
{"color": "#d6bcab", "text_color": "#7b341e", "border_color": "#b08b6e"},
|
||||
{"color": "#b08b6e", "text_color": "#ffffff", "border_color": "#966251"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Space Gray",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#1a1a1a",
|
||||
"inner_box": "#2d2d2d",
|
||||
"background": "#2d2d2d",
|
||||
"bot_name": "#e2e2e2",
|
||||
"dialog": "#ffffff",
|
||||
"narration": "#d1d1d1",
|
||||
"inner_thoughts": "#b0b0b0",
|
||||
"profile_border": "#404040",
|
||||
"box_border": "#404040",
|
||||
"image_border": "#404040",
|
||||
"divider_outer": "#404040",
|
||||
"divider_inner": "#2d2d2d",
|
||||
"gradient_start": "#1a1a1a",
|
||||
"gradient_end": "#2d2d2d"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#404040", "text_color": "#e2e2e2", "border_color": "#4a4a4a"},
|
||||
{"color": "#4a4a4a", "text_color": "#e2e2e2", "border_color": "#525252"},
|
||||
{"color": "#525252", "text_color": "#ffffff", "border_color": "#5a5a5a"}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Gradient Modern",
|
||||
"theme": {
|
||||
"colors": {
|
||||
"outer_box": "#fafafa",
|
||||
"inner_box": "#fafafa",
|
||||
"background": "#fafafa",
|
||||
"bot_name": "#494949",
|
||||
"dialog": "#494949",
|
||||
"narration": "#666666",
|
||||
"inner_thoughts": "#808080",
|
||||
"profile_border": "#e3e3e3",
|
||||
"box_border": "#e9e9e9",
|
||||
"image_border": "#e3e3e3",
|
||||
"divider_outer": "#e9e9e9",
|
||||
"divider_inner": "#e9e9e9",
|
||||
"gradient_start": "#D9D782",
|
||||
"gradient_end": "#A9B9D9",
|
||||
"tag_bg": "#494949",
|
||||
"tag_text": "#d5d5d5"
|
||||
},
|
||||
"tags": [
|
||||
{"color": "#494949", "text_color": "#d5d5d5", "border_color": "#5a5a5a"},
|
||||
{"color": "#494949", "text_color": "#d5d5d5", "border_color": "#5a5a5a"},
|
||||
{"color": "#494949", "text_color": "#d5d5d5", "border_color": "#5a5a5a"}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
function applyTemplate(self:templateStyles, theme:string){
|
||||
const themeDict = templates.find((template) => template.name == theme)
|
||||
|
||||
self.gradientModern = themeDict.gradientModern || false
|
||||
self.outerBoxColor = themeDict.theme.colors.outer_box
|
||||
self.innerBoxColor = themeDict.theme.colors.inner_box
|
||||
self.botNameColor = themeDict.theme.colors.bot_name
|
||||
self.profileBorderColor = themeDict.theme.colors.profile_border
|
||||
self.boxBorderColor = themeDict.theme.colors.box_border
|
||||
self.dividerOuterColor = themeDict.theme.colors.divider_outer
|
||||
self.dividerInnerColor = themeDict.theme.colors.divider_inner
|
||||
self.dividerSolidColor = themeDict.theme.colors.divider_outer
|
||||
self.styles.text = themeDict.theme.colors.dialog
|
||||
self.tagLayout = []
|
||||
for(let i=0; i<themeDict.theme.tags.length; i++){
|
||||
let tag = themeDict.theme.tags[i]
|
||||
self.tagLayout.push({
|
||||
content: "",
|
||||
border_radius: 5,
|
||||
font_size: 0.8,
|
||||
padding: {
|
||||
top: 0.5,
|
||||
right: 1,
|
||||
bottom: 0.5,
|
||||
left: 1
|
||||
},
|
||||
text_color: tag.text_color,
|
||||
style: "solid",
|
||||
color: tag.color
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function createDecoration(self:templateStyles, content:string){
|
||||
|
||||
let profile_section_html = ''
|
||||
if(self.gradientModern){
|
||||
|
||||
let colors = {
|
||||
"outer_box": "#fafafa",
|
||||
"profile_border": "#e3e3e3",
|
||||
"gradient_start": "#D9D782",
|
||||
"gradient_end": "#A9B9D9",
|
||||
"divider_outer": "#e9e9e9",
|
||||
"bot_name": "#ededed",
|
||||
"narration": "#494949",
|
||||
"tag_bg": "#494949",
|
||||
"tag_text": "#d5d5d5"
|
||||
}
|
||||
|
||||
let bot_name_html = ""
|
||||
|
||||
if(self.showBotName){
|
||||
let bot_name = self.botName.trim() || "봇이름"
|
||||
bot_name_html = `
|
||||
<div style="background:linear-gradient(135deg,${colors['gradient_start']},${colors['gradient_end']});
|
||||
background-size:110%;
|
||||
background-position:center;
|
||||
border-radius:20px;
|
||||
padding:10px;
|
||||
line-height:10px;
|
||||
border:solid 10px ${colors['divider_outer']};
|
||||
text-transform:uppercase;
|
||||
letter-spacing:1px;
|
||||
box-shadow:inset 0px 40px 0px rgba(30,30,30,.1);
|
||||
display:flex;
|
||||
width: fit-content;
|
||||
max-width: 200px;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
margin-top: 5px;">
|
||||
<span style="text-decoration:none;
|
||||
color:${colors['bot_name']};
|
||||
font-weight:bold;
|
||||
text-shadow:0px 0px 5px rgba(30,30,30,.1)">
|
||||
${bot_name}
|
||||
</span>
|
||||
</div>`
|
||||
}
|
||||
|
||||
let tags_html = ""
|
||||
if(self.showTags){
|
||||
let tags = []
|
||||
for(let i = 0; i < self.tagLayout.length; i++){
|
||||
let widget = self.tagLayout[i]
|
||||
let tag_text = widget.content || `태그 ${i+1}`
|
||||
tags.push(tag_text)
|
||||
}
|
||||
|
||||
if(tags.length > 0){
|
||||
tags_html = `
|
||||
<div style="margin-top: 15px;
|
||||
float: right;
|
||||
width: fit-content;
|
||||
background-color:${colors['tag_bg']};
|
||||
border-radius:5px 0px 0px 5px;
|
||||
padding:10px;
|
||||
line-height:10px;
|
||||
letter-spacing:2px;
|
||||
text-transform:uppercase;
|
||||
color:${colors['tag_text']};
|
||||
font-size:10px">
|
||||
${tags.join(' | ')}
|
||||
</div>`
|
||||
}
|
||||
}
|
||||
|
||||
let profile_image_html = ""
|
||||
|
||||
if(self.showProfile && self.showProfileImage){
|
||||
let image_url = '' //TODO
|
||||
let width = self.widthInput
|
||||
let height = self.heightInput
|
||||
let frame_style = self.frameStyle
|
||||
|
||||
let common_style = `
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0px 10px 30px rgba(0,0,0,0.1);
|
||||
border: 3px solid ${colors['profile_border']};
|
||||
`
|
||||
|
||||
let image_style = ""
|
||||
let container_style = ""
|
||||
|
||||
if(frame_style == "배너"){
|
||||
image_style = `
|
||||
${common_style}
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 15px;
|
||||
object-fit: cover;
|
||||
`
|
||||
container_style = "width: 100%; padding: 0 20px;"
|
||||
}else if(frame_style == "동그라미"){
|
||||
image_style = `
|
||||
${common_style}
|
||||
width: ${width}px;
|
||||
height: ${width}px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
`
|
||||
container_style = "width: auto;"
|
||||
}else{
|
||||
image_style = `
|
||||
${common_style}
|
||||
width: ${width}px;
|
||||
height: ${height}px;
|
||||
border-radius: 10px;
|
||||
object-fit: cover;
|
||||
`
|
||||
container_style = "width: auto;"
|
||||
}
|
||||
|
||||
profile_image_html = `
|
||||
<div style="text-align: center;
|
||||
clear: both;
|
||||
${container_style}
|
||||
padding-top: 40px;
|
||||
padding-bottom: 20px;">
|
||||
<img style="${image_style}"
|
||||
src="${image_url}"
|
||||
alt="profile"
|
||||
class="fr-fic fr-dii">
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
return `
|
||||
<p><br></p>
|
||||
<div style="border:solid 2px ${colors['profile_border']};
|
||||
background-color:${colors['outer_box']};
|
||||
border-radius:20px;
|
||||
position:relative;
|
||||
max-width:500px;
|
||||
margin:0px auto;">
|
||||
|
||||
<div style="height: 85px;margin:-1px -1px 0px -1px">
|
||||
<div style="background:linear-gradient(-45deg,${colors['gradient_start']},${colors['gradient_end']});
|
||||
background-size:200%;
|
||||
height:70px;
|
||||
border-radius:19px 19px 0px 0px">
|
||||
<div style="height:70px;width:100%;border-radius:19px 19px 0px 0px">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${bot_name_html}
|
||||
${profile_image_html}
|
||||
${tags_html}
|
||||
|
||||
|
||||
<div style="padding: 40px 60px 30px 60px;
|
||||
line-height:22px;
|
||||
letter-spacing:.35px;
|
||||
clear: both;">
|
||||
${content}
|
||||
</div>
|
||||
</div>
|
||||
<p><br></p>`
|
||||
|
||||
}
|
||||
else{
|
||||
let box_outer_color = self.outerBoxColor
|
||||
let box_inner_color = self.innerBoxColor
|
||||
let shadow_value = self.shadowIntensity
|
||||
|
||||
let border_style = ""
|
||||
if(self.useBoxBorder){
|
||||
let border_color = self.boxBorderColor
|
||||
let border_thickness = self.boxBorderThickness
|
||||
border_style = `border: ${border_thickness}px solid ${border_color};`
|
||||
}
|
||||
|
||||
let background_color = ""
|
||||
let inner_box_style = ""
|
||||
if(self.showInnerBox){
|
||||
background_color = box_outer_color
|
||||
inner_box_style = `
|
||||
font-size:${self.styles.font_size_normal}px;
|
||||
background:${box_inner_color};
|
||||
padding:${self.styles.spacing_large}px;
|
||||
border-radius:${self.styles.radius_normal}px;`
|
||||
}
|
||||
else{
|
||||
background_color = box_inner_color
|
||||
inner_box_style = `
|
||||
font-size:${self.styles.font_size_normal}px;
|
||||
padding:0;`
|
||||
}
|
||||
|
||||
if(self.showProfile){
|
||||
let profile_parts = []
|
||||
if(self.showProfileImage){
|
||||
let profile_border_color = self.profileBorderColor
|
||||
let width = self.widthInput
|
||||
let height = self.heightInput
|
||||
let image_url = '' //TODO
|
||||
|
||||
let common_style = `
|
||||
max-width:100%;
|
||||
${self.showProfileShadow ? 'box-shadow:rgba(0,0,0,0.12) 0px 4px 16px;' : ''}
|
||||
${self.showProfileBorder ? `border:3px solid ${profile_border_color};` : ''}
|
||||
`
|
||||
|
||||
let profile_style = ""
|
||||
let container_style = ""
|
||||
|
||||
if(self.frameStyle == "배너"){
|
||||
profile_style = `${common_style} border-radius:12px;`
|
||||
container_style = "width:100%;"
|
||||
}else if(self.frameStyle == "동그라미"){
|
||||
profile_style = `${common_style} width:${width}px; height:${width}px; border-radius:50%; object-fit:cover;`
|
||||
container_style = "width:auto;"
|
||||
}else{
|
||||
profile_style = `${common_style} width:${width}px; height:${height}px; border-radius:8px; object-fit:cover;`
|
||||
container_style = "width:auto;"
|
||||
}
|
||||
|
||||
let profile_html = `
|
||||
<div style="margin-bottom:1rem; text-align:center; ${container_style}">
|
||||
<img style="${profile_style}"
|
||||
src="${image_url}"
|
||||
alt="profile"
|
||||
class="fr-fic fr-dii">
|
||||
</div>
|
||||
`
|
||||
profile_parts.push(profile_html)
|
||||
}
|
||||
if(self.showBotName){
|
||||
let bot_name = self.botName || "봇 이름"
|
||||
let bot_name_color = self.botNameColor
|
||||
let bot_name_html = `
|
||||
<h3 style="color:${bot_name_color};font-weight:${self.styles.font_weight_bold};">${bot_name}</h3>
|
||||
`
|
||||
profile_parts.push(bot_name_html)
|
||||
}
|
||||
if(self.showTags){
|
||||
let tags_html = []
|
||||
for(let i = 0; i < self.tagLayout.length; i++){
|
||||
let widget = self.tagLayout[i]
|
||||
if(widget){
|
||||
let style_dict = widget
|
||||
let tag_text = style_dict.content || `태그 ${i+1}`
|
||||
let css_styles = [
|
||||
"display:inline-block",
|
||||
`border-radius:${style_dict.border_radius}px`,
|
||||
`font-size:${style_dict.font_size}rem`,
|
||||
`padding:${style_dict.padding.top}rem ${style_dict.padding.right}rem`,
|
||||
`${style_dict.padding.bottom}rem ${style_dict.padding.left}rem`,
|
||||
`color:${style_dict.text_color}`
|
||||
]
|
||||
|
||||
if(style_dict.style == "transparent_bg"){
|
||||
css_styles.push(
|
||||
"background:transparent",
|
||||
`border:1px solid ${style_dict.color}`
|
||||
)
|
||||
}else if(style_dict.style == "gradient"){
|
||||
let base_color:string = style_dict.color //hex
|
||||
|
||||
let base_color_rgb = parseInt(base_color, 16)
|
||||
let r = (base_color_rgb >> 16) & 255
|
||||
let g = (base_color_rgb >> 8) & 255
|
||||
let b = base_color_rgb & 255
|
||||
|
||||
let light_color = `#${Math.min(255, r+120).toString(16)}${Math.min(255, g+120).toString(16)}${Math.min(255, b+120).toString(16)}`
|
||||
let dark_color = `#${Math.max(0, r-120).toString(16)}${Math.max(0, g-120).toString(16)}${Math.max(0, b-120).toString(16)}`
|
||||
|
||||
css_styles.push(
|
||||
`background:linear-gradient(135deg, ${light_color}, ${dark_color})`,
|
||||
"border:none"
|
||||
)
|
||||
}else{
|
||||
css_styles.push(
|
||||
`background:${style_dict.color}`,
|
||||
"border:none"
|
||||
)
|
||||
}
|
||||
|
||||
let tag_html = `
|
||||
<span style="${css_styles.join(';')}">
|
||||
${tag_text}
|
||||
</span>
|
||||
`
|
||||
tags_html.push(tag_html)
|
||||
}
|
||||
}
|
||||
|
||||
if(tags_html.length > 0){
|
||||
let container_styles = [
|
||||
"text-align:center",
|
||||
"margin:0 auto",
|
||||
"max-width:fit-content"
|
||||
]
|
||||
|
||||
let tags_container = `
|
||||
<div style="${container_styles.join(';')}">
|
||||
${tags_html.join('')}
|
||||
</div>
|
||||
`
|
||||
profile_parts.push(tags_container)
|
||||
}
|
||||
}
|
||||
|
||||
if(self.showDivider){
|
||||
let thickness = self.dividerThickness
|
||||
let divider_style = ""
|
||||
if(self.dividerStyle == "gradient"){
|
||||
let divider_outer_color = self.dividerOuterColor
|
||||
let divider_inner_color = self.dividerInnerColor
|
||||
divider_style = `background:linear-gradient(to right,${divider_outer_color} 0%,${divider_inner_color} 50%,${divider_outer_color} 100%);`
|
||||
}else{
|
||||
let solid_color = self.dividerSolidColor
|
||||
divider_style = `background:${solid_color};`
|
||||
}
|
||||
|
||||
let divider_html = `
|
||||
<div style="height:${thickness}px;${divider_style}margin:1rem 0;border-radius:${thickness/2}px;">
|
||||
<br>
|
||||
</div>
|
||||
`
|
||||
profile_parts.push(divider_html)
|
||||
}
|
||||
|
||||
if(profile_parts.length > 0){
|
||||
profile_section_html = `
|
||||
<div style="display:flex;flex-direction:column;text-align:center;margin-bottom:1.25rem;">
|
||||
${profile_parts.join('')}
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
return `
|
||||
<p><br></p>
|
||||
<p><br></p>
|
||||
<div style="font-family:${self.styles.font_family};
|
||||
color:${self.styles.text};
|
||||
line-height:1.8;
|
||||
width:100%;
|
||||
max-width:600px;
|
||||
margin:1rem auto;
|
||||
background:${background_color};
|
||||
border-radius:${self.styles.radius_large}px;
|
||||
box-shadow:0px ${shadow_value}px ${shadow_value * 2}px rgba(0,0,0,0.2);
|
||||
${border_style}">
|
||||
<div style="padding:${self.styles.spacing_large}px;">
|
||||
<div style="${inner_box_style}">
|
||||
${profile_section_html}
|
||||
${content}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p><br></p>
|
||||
<p><br></p>`
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
1068
src/ts/model/modellist.ts
Normal file
1068
src/ts/model/modellist.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,200 +0,0 @@
|
||||
|
||||
export function getModelName(name:string){
|
||||
switch(name){
|
||||
case "gpt35":
|
||||
return "GPT-3.5 Turbo"
|
||||
case "gpt35_0613":
|
||||
return "GPT-3.5 Turbo 0613"
|
||||
case "gpt35_0301":
|
||||
return "GPT-3.5 Turbo 0301"
|
||||
case "gpt35_16k":
|
||||
return "GPT-3.5 Turbo 16k"
|
||||
case "gpt35_16k_0613":
|
||||
return "GPT-3.5 Turbo 16k 0613"
|
||||
case 'instructgpt35':
|
||||
return 'GPT-3.5 Turbo Instruct'
|
||||
case "gpt4":
|
||||
return "GPT-4"
|
||||
case "gpt4_0301":
|
||||
return "GPT-4 0301"
|
||||
case "gpt4_32k":
|
||||
return "GPT-4 32k"
|
||||
case "gpt4_0613":
|
||||
return "GPT-4 0613"
|
||||
case "gpt4_32k_0613":
|
||||
return "GPT-4 32k 0613"
|
||||
case "gpt4_1106":
|
||||
return "GPT-4 Turbo 1106"
|
||||
case 'gpt45':
|
||||
return 'GPT-4.5'
|
||||
case "gpt35_1106":
|
||||
return "GPT-3.5 Turbo 1106"
|
||||
case 'local_gptq':
|
||||
return 'Local Model GPTQ'
|
||||
case "palm2":
|
||||
return "PaLM2 Bison"
|
||||
case "textgen_webui":
|
||||
return "Oobabooga Legacy"
|
||||
case 'ooba':
|
||||
return 'Oobabooga'
|
||||
case "mancer":
|
||||
return "Mancer"
|
||||
case "kobold":
|
||||
return "Kobold"
|
||||
case "custom":
|
||||
return "Plugin"
|
||||
case "novelai":
|
||||
return "NovelAI Clio"
|
||||
case "novelai_kayra":
|
||||
return "NovelAI Kayra"
|
||||
case "novellist":
|
||||
return "NovelList SuperTrin"
|
||||
case "novellist damsel":
|
||||
return "NovelList Damsel"
|
||||
case 'reverse_proxy':
|
||||
return "Custom (OpenAI-compatible)"
|
||||
case 'openrouter':
|
||||
return "OpenRouter"
|
||||
case 'gptvi4_1106':
|
||||
return "GPT-4 Turbo 1106 Vision"
|
||||
case 'palm2_unicorn':
|
||||
return "PaLM2 Unicorn"
|
||||
case 'mistral-tiny':
|
||||
return "Mistral Tiny"
|
||||
case 'mistral-small':
|
||||
return "Mistral Small"
|
||||
case 'mistral-medium':
|
||||
return "Mistral Medium"
|
||||
case 'gemini-pro':
|
||||
return "Gemini Pro"
|
||||
case 'horde:::auto':
|
||||
return 'Horde Auto Model'
|
||||
case 'gpt4_0125':
|
||||
return 'GPT-4 Turbo 0125'
|
||||
case 'gpt35_0125':
|
||||
return 'GPT-3.5 Turbo 0125'
|
||||
case 'gemini-ultra':
|
||||
return 'Gemini Ultra'
|
||||
case 'gemini-ultra-vision':
|
||||
return 'Gemini Ultra Vision'
|
||||
case 'claude-3-opus-20240229':
|
||||
return 'Claude 3 Opus (20240229)'
|
||||
case 'claude-3-5-sonnet-20240620':
|
||||
return 'Claude 3.5 Sonnet (20240620)'
|
||||
case 'claude-3-sonnet-20240229':
|
||||
return 'Claude 3 Sonnet (20240229)'
|
||||
case 'mistral-large-latest':
|
||||
return 'Mistral Large'
|
||||
case 'mistral-small-latest':
|
||||
return 'Mistral Small'
|
||||
case 'mistral-medium-latest':
|
||||
return 'Mistral Medium'
|
||||
case 'claude-3-haiku-20240307':
|
||||
return 'Claude 3 Haiku (20240307)'
|
||||
case 'gpt4_turbo':
|
||||
return 'GPT-4 Turbo'
|
||||
case 'gpt4_turbo_20240409':
|
||||
return 'GPT-4 Turbo (20240409)'
|
||||
case 'gpt4o':
|
||||
return 'GPT-4o'
|
||||
case 'gpt4o-2024-05-13':
|
||||
return 'GPT-4o (2024-05-13)'
|
||||
case 'gpt4o-2024-08-06':
|
||||
return 'GPT-4o (2024-08-06)'
|
||||
case 'gpt4o-chatgpt':
|
||||
return 'GPT-4o ChatGPT'
|
||||
case 'gpt4om':
|
||||
return 'GPT-4o Mini'
|
||||
case 'gpt4o1-preview':
|
||||
return 'o1 Preview'
|
||||
case 'gpt4o1-mini':
|
||||
return 'o1 Mini'
|
||||
case 'gpt4om-2024-07-18':
|
||||
return 'GPT-4o Mini (2024-07-18)'
|
||||
case 'gemini-1.5-pro-latest':
|
||||
return 'Gemini 1.5 Pro'
|
||||
case 'gemini-1.5-pro-exp-0801':
|
||||
return 'Gemini 1.5 Pro Exp (0801)'
|
||||
case 'gemini-1.5-pro-exp-0827':
|
||||
return 'Gemini 1.5 Pro Exp (0827)'
|
||||
case 'gemini-1.5-flash':
|
||||
return 'Gemini 1.5 Flash'
|
||||
case 'ollama-hosted':
|
||||
return 'Ollama'
|
||||
case 'cohere-command-r':
|
||||
return 'Cohere Command-R'
|
||||
case 'cohere-command-r-plus':
|
||||
return 'Cohere Command-R Plus'
|
||||
default:
|
||||
if(name.startsWith("horde:::")){
|
||||
const split = name.split(":::")
|
||||
return `Horde ${split[1]}`
|
||||
}
|
||||
if(name.startsWith('tf:::')){
|
||||
const split = name.split(":::")
|
||||
return `${split[1]}`
|
||||
}
|
||||
if(name.startsWith('local_')){
|
||||
const realName = name.replace('local_', '').split(/(\\|\/)/g).at(-1)
|
||||
return `GGUF ${realName}`
|
||||
}
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
export function getModelShortName(model:string){
|
||||
if(model.startsWith("gpt35")){
|
||||
return "GPT-3.5"
|
||||
}
|
||||
if(model.startsWith("cohere-")){
|
||||
return model.replace("cohere-", "")
|
||||
}
|
||||
if(model.startsWith('gpt4om')){
|
||||
return "GPT-4o Mini"
|
||||
}
|
||||
if(model.startsWith("gpt4o")){
|
||||
return "GPT-4o"
|
||||
}
|
||||
if(model.startsWith("gpt4")){
|
||||
return "GPT-4"
|
||||
}
|
||||
if(model.startsWith("gptvi4")){
|
||||
return "GPT-4V"
|
||||
}
|
||||
if(model.startsWith("mistral")){
|
||||
return getModelName(model).split(" ").at(-1)
|
||||
}
|
||||
if(model.startsWith("mancer")){
|
||||
return "Mancer"
|
||||
}
|
||||
if(model.startsWith('tf:::')){
|
||||
const split = model.split(":::")
|
||||
return split[1]
|
||||
}
|
||||
if(model.startsWith('local_')){
|
||||
const realName = model.replace('local_', '').split(/(\\|\/)/g).at(-1)
|
||||
return realName
|
||||
}
|
||||
if(model.startsWith('horde:::')){
|
||||
const split = model.split(":::")
|
||||
return split[1]
|
||||
}
|
||||
|
||||
if(model.startsWith('claude-3')){
|
||||
const split = model.split("-")
|
||||
if(!isNaN(parseInt(split[split.length-1]))){
|
||||
return split[split.length-2]
|
||||
}
|
||||
else{
|
||||
return split[split.length-1]
|
||||
}
|
||||
}
|
||||
if(model.startsWith('reverse_proxy')){
|
||||
return 'Custom'
|
||||
}
|
||||
if(model.startsWith('oaicomp')){
|
||||
return 'Custom'
|
||||
}
|
||||
return getModelName(model)
|
||||
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
import { get } from "svelte/store"
|
||||
import { DataBase } from "../storage/database"
|
||||
import { getDatabase } from "../storage/database.svelte"
|
||||
|
||||
export async function openRouterModels() {
|
||||
try {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let headers = {
|
||||
"Authorization": "Bearer " + db.openrouterKey,
|
||||
"Content-Type": "application/json"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { get } from "svelte/store";
|
||||
import { runTrigger } from "./process/triggers";
|
||||
import { CurrentCharacter, CurrentChat } from "./stores";
|
||||
import { runCharacterJS } from "./plugins/embedscript";
|
||||
import { sleep } from "./util";
|
||||
import { getCurrentCharacter, getCurrentChat, setCurrentChat } from "./storage/database.svelte";
|
||||
|
||||
|
||||
function nodeObserve(node:HTMLElement){
|
||||
@@ -15,17 +14,17 @@ function nodeObserve(node:HTMLElement){
|
||||
}
|
||||
if(triggerName){
|
||||
node.addEventListener('click', async () => {
|
||||
const currentChar = get(CurrentCharacter)
|
||||
const currentChar = getCurrentCharacter()
|
||||
if(currentChar.type === 'group'){
|
||||
return;
|
||||
}
|
||||
const triggerResult = await runTrigger(currentChar, 'manual', {
|
||||
chat: get(CurrentChat),
|
||||
chat: getCurrentChat(),
|
||||
manualName: triggerName,
|
||||
});
|
||||
|
||||
if(triggerResult){
|
||||
CurrentChat.set(triggerResult.chat);
|
||||
setCurrentChat(triggerResult.chat);
|
||||
}
|
||||
|
||||
}, {
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import DOMPurify from 'isomorphic-dompurify';
|
||||
import markdownit from 'markdown-it'
|
||||
import { DataBase, setDatabase, type Database, type Message, type character, type customscript, type groupChat, type triggerscript } from './storage/database';
|
||||
import { getFileSrc } from './storage/globalApi';
|
||||
import { getCurrentCharacter, type Database, type Message, type character, type customscript, type groupChat, type triggerscript } from './storage/database.svelte';
|
||||
import { DBState } from './stores.svelte';
|
||||
import { getFileSrc } from './globalApi.svelte';
|
||||
import { processScriptFull } from './process/scripts';
|
||||
import { get } from 'svelte/store';
|
||||
import css, { type CssAtRuleAST } from '@adobe/css-tools'
|
||||
import { CurrentCharacter, SizeStore, selectedCharID } from './stores';
|
||||
import { SizeStore, selectedCharID } from './stores.svelte';
|
||||
import { calcString } from './process/infunctions';
|
||||
import { findCharacterbyId, getPersonaPrompt, getUserIcon, getUserName, parseKeyValue, sfc32, sleep, uuidtoNumber } from './util';
|
||||
import { getInlayImage } from './process/files/image';
|
||||
import { getModuleAssets, getModuleLorebooks } from './process/modules';
|
||||
import type { OpenAIChat } from './process';
|
||||
import type { OpenAIChat } from './process/index.svelte';
|
||||
import hljs from 'highlight.js/lib/core'
|
||||
import 'highlight.js/styles/atom-one-dark.min.css'
|
||||
|
||||
@@ -73,17 +74,21 @@ DOMPurify.addHook("uponSanitizeAttribute", (node, data) => {
|
||||
}
|
||||
})
|
||||
|
||||
DOMPurify.addHook('uponSanitizeAttribute', (node, data) => {
|
||||
if (['IMG', 'SOURCE', 'STYLE'].includes(node.nodeName) && data.attrName === 'src' && data.attrValue.startsWith('asset://localhost/')) {
|
||||
data.forceKeepAttr = true;
|
||||
}
|
||||
});
|
||||
|
||||
function renderMarkdown(md:markdownit, data:string){
|
||||
const db = get(DataBase)
|
||||
let quotes = ['“', '”', '‘', '’']
|
||||
if(db?.customQuotes){
|
||||
quotes = db.customQuotesData ?? quotes
|
||||
if(DBState.db?.customQuotes){
|
||||
quotes = DBState.db.customQuotesData ?? quotes
|
||||
}
|
||||
|
||||
let text = md.render(data.replace(/“|”/g, '"').replace(/‘|’/g, "'"))
|
||||
|
||||
if(db?.unformatQuotes){
|
||||
if(DBState.db?.unformatQuotes){
|
||||
text = text.replace(/\uE9b0/gu, quotes[0]).replace(/\uE9b1/gu, quotes[1])
|
||||
text = text.replace(/\uE9b2/gu, quotes[2]).replace(/\uE9b3/gu, quotes[3])
|
||||
}
|
||||
@@ -254,8 +259,7 @@ async function renderHighlightableMarkdown(data:string) {
|
||||
export const assetRegex = /{{(raw|path|img|image|video|audio|bg|emotion|asset|video-img|source)::(.+?)}}/g
|
||||
|
||||
async function parseAdditionalAssets(data:string, char:simpleCharacterArgument|character, mode:'normal'|'back', mode2:'unset'|'pre'|'post' = 'unset'){
|
||||
const db = get(DataBase)
|
||||
const assetWidthString = (db.assetWidth && db.assetWidth !== -1 || db.assetWidth === 0) ? `max-width:${db.assetWidth}rem;` : ''
|
||||
const assetWidthString = (DBState.db.assetWidth && DBState.db.assetWidth !== -1 || DBState.db.assetWidth === 0) ? `max-width:${DBState.db.assetWidth}rem;` : ''
|
||||
|
||||
let assetPaths:{[key:string]:{
|
||||
path:string
|
||||
@@ -348,7 +352,7 @@ async function parseAdditionalAssets(data:string, char:simpleCharacterArgument|c
|
||||
})
|
||||
|
||||
if(needsSourceAccess){
|
||||
const chara = get(CurrentCharacter)
|
||||
const chara = getCurrentCharacter()
|
||||
if(chara.image){}
|
||||
data = data.replace(/\uE9b4CHAR\uE9b4/g,
|
||||
chara.image ? (await getFileSrc(chara.image)) : ''
|
||||
@@ -479,7 +483,9 @@ function decodeStyle(text:string){
|
||||
|
||||
return text.replaceAll(styleDecodeRegex, (full, txt:string) => {
|
||||
try {
|
||||
const ast = css.parse(Buffer.from(txt, 'hex').toString('utf-8'))
|
||||
let text = Buffer.from(txt, 'hex').toString('utf-8')
|
||||
text = risuChatParser(text)
|
||||
const ast = css.parse(text)
|
||||
const rules = ast?.stylesheet?.rules
|
||||
if(rules){
|
||||
for(let i=0;i<rules.length;i++){
|
||||
@@ -500,7 +506,7 @@ export async function hasher(data:Uint8Array){
|
||||
}
|
||||
|
||||
export async function convertImage(data:Uint8Array) {
|
||||
if(!get(DataBase).imageCompression){
|
||||
if(!DBState.db.imageCompression){
|
||||
return data
|
||||
}
|
||||
const type = checkImageType(data)
|
||||
@@ -1775,16 +1781,21 @@ export function risuChatParser(da:string, arg:{
|
||||
cbsConditions?:CbsConditions
|
||||
} = {}):string{
|
||||
const chatID = arg.chatID ?? -1
|
||||
const db = arg.db ?? get(DataBase)
|
||||
const db = arg.db ?? DBState.db
|
||||
const aChara = arg.chara
|
||||
const visualize = arg.visualize ?? false
|
||||
let chara:character|string = null
|
||||
|
||||
if(aChara){
|
||||
if(typeof(aChara) !== 'string' && aChara.type === 'group'){
|
||||
const gc = findCharacterbyId(aChara.chats[aChara.chatPage].message.at(-1).saying ?? '')
|
||||
if(gc.name !== 'Unknown Character'){
|
||||
chara = gc
|
||||
if(aChara.chats[aChara.chatPage].message.length > 0){
|
||||
const gc = findCharacterbyId(aChara.chats[aChara.chatPage].message.at(-1).saying ?? '')
|
||||
if(gc.name !== 'Unknown Character'){
|
||||
chara = gc
|
||||
}
|
||||
}
|
||||
else{
|
||||
chara = 'bot'
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -1792,7 +1803,7 @@ export function risuChatParser(da:string, arg:{
|
||||
}
|
||||
}
|
||||
if(arg.tokenizeAccurate){
|
||||
const db = arg.db ?? get(DataBase)
|
||||
const db = arg.db ?? DBState.db
|
||||
const selchar = chara ?? db.characters[get(selectedCharID)]
|
||||
if(!selchar){
|
||||
chara = 'bot'
|
||||
@@ -2098,9 +2109,8 @@ export function risuChatParser(da:string, arg:{
|
||||
|
||||
|
||||
export function getChatVar(key:string){
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
const char = DBState.db.characters[selectedChar]
|
||||
if(!char){
|
||||
return 'null'
|
||||
}
|
||||
@@ -2108,7 +2118,7 @@ export function getChatVar(key:string){
|
||||
chat.scriptstate = chat.scriptstate ?? {}
|
||||
const state = (chat.scriptstate['$' + key])
|
||||
if(state === undefined || state === null){
|
||||
const defaultVariables = parseKeyValue(char.defaultVariables).concat(parseKeyValue(db.templateDefaultVariables))
|
||||
const defaultVariables = parseKeyValue(char.defaultVariables).concat(parseKeyValue(DBState.db.templateDefaultVariables))
|
||||
const findResult = defaultVariables.find((f) => {
|
||||
return f[0] === key
|
||||
})
|
||||
@@ -2121,20 +2131,15 @@ export function getChatVar(key:string){
|
||||
}
|
||||
|
||||
export function getGlobalChatVar(key:string){
|
||||
const db = get(DataBase)
|
||||
return db.globalChatVariables[key] ?? 'null'
|
||||
return DBState.db.globalChatVariables[key] ?? 'null'
|
||||
}
|
||||
|
||||
export function setChatVar(key:string, value:string){
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
const chat = char.chats[char.chatPage]
|
||||
chat.scriptstate = chat.scriptstate ?? {}
|
||||
chat.scriptstate['$' + key] = value
|
||||
char.chats[char.chatPage] = chat
|
||||
db.characters[selectedChar] = char
|
||||
setDatabase(db)
|
||||
if(!DBState.db.characters[selectedChar].chats[DBState.db.characters[selectedChar].chatPage].scriptstate){
|
||||
DBState.db.characters[selectedChar].chats[DBState.db.characters[selectedChar].chatPage].scriptstate = {}
|
||||
}
|
||||
DBState.db.characters[selectedChar].chats[DBState.db.characters[selectedChar].chatPage].scriptstate['$' + key] = value
|
||||
}
|
||||
|
||||
|
||||
@@ -2278,4 +2283,4 @@ export function parseChatML(data:string):OpenAIChat[]|null{
|
||||
content: v
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
import { get } from "svelte/store"
|
||||
import { DataBase, saveImage, setDatabase } from "./storage/database"
|
||||
import { getDatabase, saveImage, setDatabase } from "./storage/database.svelte"
|
||||
import { getUserName, selectSingleFile, sleep } from "./util"
|
||||
import { alertError, alertNormal, alertStore } from "./alert"
|
||||
import { downloadFile, readImage } from "./storage/globalApi"
|
||||
import { downloadFile, readImage } from "./globalApi.svelte"
|
||||
import { language } from "src/lang"
|
||||
import { reencodeImage } from "./process/files/image"
|
||||
import { PngChunk } from "./pngChunk"
|
||||
@@ -14,7 +14,7 @@ export async function selectUserImg() {
|
||||
return
|
||||
}
|
||||
const img = selected.data
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const imgp = await saveImage(img)
|
||||
db.userIcon = imgp
|
||||
db.personas[db.selectedPersona] = {
|
||||
@@ -27,7 +27,7 @@ export async function selectUserImg() {
|
||||
}
|
||||
|
||||
export function saveUserPersona() {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
db.personas[db.selectedPersona].name=db.username
|
||||
db.personas[db.selectedPersona].icon=db.userIcon,
|
||||
db.personas[db.selectedPersona].personaPrompt=db.personaPrompt,
|
||||
@@ -39,7 +39,7 @@ export function changeUserPersona(id:number, save:'save'|'noSave' = 'save') {
|
||||
if(save === 'save'){
|
||||
saveUserPersona()
|
||||
}
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const pr = db.personas[id]
|
||||
db.personaPrompt = pr.personaPrompt
|
||||
db.username = pr.name,
|
||||
@@ -56,7 +56,7 @@ interface PersonaCard {
|
||||
}
|
||||
|
||||
export async function exportUserPersona(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase({snapshot: true})
|
||||
if(!db.userIcon){
|
||||
alertError(language.errors.noUserIcon)
|
||||
return
|
||||
@@ -69,7 +69,7 @@ export async function exportUserPersona(){
|
||||
|
||||
let img = await readImage(db.userIcon)
|
||||
|
||||
let card:PersonaCard = structuredClone({
|
||||
let card:PersonaCard = safeStructuredClone({
|
||||
name: db.username,
|
||||
personaPrompt: db.personaPrompt,
|
||||
})
|
||||
@@ -107,7 +107,7 @@ export async function importUserPersona(){
|
||||
}
|
||||
const data:PersonaCard = JSON.parse(Buffer.from(decoded, 'base64').toString('utf-8'))
|
||||
if(data.name && data.personaPrompt){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
db.personas.push({
|
||||
name: data.name,
|
||||
icon: await saveImage(await reencodeImage(v.data)),
|
||||
|
||||
@@ -2,9 +2,9 @@ import { get } from 'svelte/store'
|
||||
import type { ScriptMode } from '../process/scripts'
|
||||
//@ts-ignore
|
||||
import WorkerUrl from './embedworker?worker&url'
|
||||
import { DataBase, type Message } from '../storage/database'
|
||||
import { selectedCharID } from '../stores'
|
||||
import { setDatabase } from '../storage/database'
|
||||
import { getDatabase, type Message } from '../storage/database.svelte'
|
||||
import { selectedCharID } from '../stores.svelte'
|
||||
import { setDatabase } from '../storage/database.svelte'
|
||||
|
||||
let worker = new Worker(WorkerUrl, {type: 'module'})
|
||||
|
||||
@@ -77,14 +77,16 @@ function runVirtualJS(code:string){
|
||||
}
|
||||
|
||||
addWorkerFunction('getChat', async () => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase({
|
||||
snapshot: true
|
||||
})
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return structuredClone(char.chats[char.chatPage].message)
|
||||
return safeStructuredClone(char.chats[char.chatPage].message)
|
||||
})
|
||||
|
||||
addWorkerFunction('setChat', async (data:Message[]) => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
let newChat:Message[] = []
|
||||
for(const dat of data){
|
||||
@@ -117,14 +119,14 @@ addWorkerFunction('setChat', async (data:Message[]) => {
|
||||
})
|
||||
|
||||
addWorkerFunction('getName', async () => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.name
|
||||
})
|
||||
|
||||
addWorkerFunction('setName', async (data:string) => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof data !== 'string'){
|
||||
return false
|
||||
@@ -135,7 +137,7 @@ addWorkerFunction('setName', async (data:string) => {
|
||||
})
|
||||
|
||||
addWorkerFunction('getDescription', async () => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
if(char.type === 'group'){
|
||||
@@ -145,7 +147,7 @@ addWorkerFunction('getDescription', async () => {
|
||||
})
|
||||
|
||||
addWorkerFunction('setDescription', async (data:string) => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char =db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
@@ -161,14 +163,14 @@ addWorkerFunction('setDescription', async (data:string) => {
|
||||
})
|
||||
|
||||
addWorkerFunction('getCharacterFirstMessage', async () => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.firstMessage
|
||||
})
|
||||
|
||||
addWorkerFunction('setCharacterFirstMessage', async (data:string) => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
@@ -181,14 +183,14 @@ addWorkerFunction('setCharacterFirstMessage', async (data:string) => {
|
||||
})
|
||||
|
||||
addWorkerFunction('getBackgroundEmbedding', async () => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.backgroundHTML
|
||||
})
|
||||
|
||||
addWorkerFunction('setBackgroundEmbedding', async (data:string) => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof data !== 'string'){
|
||||
return false
|
||||
@@ -200,7 +202,7 @@ addWorkerFunction('setBackgroundEmbedding', async (data:string) => {
|
||||
|
||||
|
||||
addWorkerFunction('getState', async (statename) => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
const chat = char.chats[char.chatPage]
|
||||
@@ -208,7 +210,7 @@ addWorkerFunction('getState', async (statename) => {
|
||||
})
|
||||
|
||||
addWorkerFunction('setState', async (statename, data) => {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
const chat = char.chats[char.chatPage]
|
||||
@@ -243,12 +245,9 @@ export async function runCharacterJS(arg:{
|
||||
mode: ScriptMode|'onButtonClick'|'modifyRequestChat'
|
||||
data: any
|
||||
}):Promise<any>{
|
||||
const perf = performance.now()
|
||||
try {
|
||||
if(arg.code === null){
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
arg.code = db.characters[selectedChar].virtualscript
|
||||
}
|
||||
arg.code = arg.code ?? ''
|
||||
const codes = {
|
||||
"editinput": 'editInput',
|
||||
"editoutput": 'editOutput',
|
||||
@@ -318,5 +317,8 @@ export async function runCharacterJS(arg:{
|
||||
}
|
||||
return arg.data
|
||||
}
|
||||
finally{
|
||||
console.log('runCharacterJS',performance.now() - perf)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { get, writable } from "svelte/store";
|
||||
import { language } from "../../lang";
|
||||
import { alertError } from "../alert";
|
||||
import { DataBase } from "../storage/database";
|
||||
import { getDatabase, setDatabaseLite } from "../storage/database.svelte";
|
||||
import { checkNullish, selectSingleFile, sleep } from "../util";
|
||||
import type { OpenAIChat } from "../process";
|
||||
import { globalFetch } from "../storage/globalApi";
|
||||
import { selectedCharID } from "../stores";
|
||||
import type { OpenAIChat } from "../process/index.svelte";
|
||||
import { globalFetch } from "../globalApi.svelte";
|
||||
import { selectedCharID } from "../stores.svelte";
|
||||
import { addAdditionalCharaJS } from "./embedscript";
|
||||
|
||||
export const customProviderStore = writable([] as string[])
|
||||
@@ -29,7 +29,7 @@ export type RisuPlugin = ProviderPlugin
|
||||
|
||||
export async function importPlugin(){
|
||||
try {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const f = await selectSingleFile(['js'])
|
||||
if(!f){
|
||||
return
|
||||
@@ -96,7 +96,7 @@ export async function importPlugin(){
|
||||
db.plugins ??= []
|
||||
db.plugins.push(pluginData)
|
||||
|
||||
DataBase.set(db)
|
||||
setDatabaseLite(db)
|
||||
loadPlugins()
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
@@ -123,7 +123,7 @@ function postMsgPluginWorker(type:string, body:any){
|
||||
let pluginTranslator = false
|
||||
|
||||
export async function loadPlugins() {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(pluginWorker){
|
||||
pluginWorker.terminate()
|
||||
pluginWorker = null
|
||||
@@ -219,7 +219,7 @@ export async function loadPlugins() {
|
||||
}
|
||||
case "getArg":{
|
||||
try {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const arg:string[] = data.body.arg.split('::')
|
||||
for(const plug of db.plugins){
|
||||
if(arg[0] === plug.name){
|
||||
@@ -243,7 +243,7 @@ export async function loadPlugins() {
|
||||
break
|
||||
}
|
||||
case "getChar":{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const charid = get(selectedCharID)
|
||||
const char = db.characters[charid]
|
||||
postMsgPluginWorker('fetchData',{
|
||||
@@ -253,7 +253,7 @@ export async function loadPlugins() {
|
||||
break
|
||||
}
|
||||
case "setChar":{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const charid = get(selectedCharID)
|
||||
db.characters[charid] = data.body
|
||||
break
|
||||
@@ -303,7 +303,7 @@ export async function pluginProcess(arg:{
|
||||
bias: {[key:string]:string}
|
||||
}|{}){
|
||||
try {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(!pluginWorker){
|
||||
return {
|
||||
success: false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import crc32 from 'crc/crc32';
|
||||
import { AppendableBuffer, VirtualWriter, type LocalWriter } from './storage/globalApi';
|
||||
import { AppendableBuffer, VirtualWriter, type LocalWriter } from './globalApi.svelte';
|
||||
import { blobToUint8Array } from './util';
|
||||
|
||||
class StreamChunkWriter{
|
||||
|
||||
@@ -2,29 +2,48 @@ import { ReadableStream, WritableStream, TransformStream } from "web-streams-pol
|
||||
import { Buffer as BufferPolyfill } from 'buffer'
|
||||
import { polyfill as dragPolyfill} from "mobile-drag-drop"
|
||||
import {scrollBehaviourDragImageTranslateOverride} from 'mobile-drag-drop/scroll-behaviour'
|
||||
import rfdc from 'rfdc'
|
||||
/**
|
||||
* Safe variant of structuredClone for svelte 5 states
|
||||
* if structuredClone is not available, it will use JSON.parse(JSON.stringify(data)) instead
|
||||
*/
|
||||
|
||||
export function polyfill() {
|
||||
try {
|
||||
const testDom = document.createElement('div');
|
||||
const supports = ('draggable' in testDom) || ('ondragstart' in testDom && 'ondrop' in testDom);
|
||||
const isIos = navigator.userAgent ? (!!navigator.userAgent.match('iPhone OS') || !!navigator.userAgent.match('iPad')) : false
|
||||
testDom.remove()
|
||||
|
||||
if((!supports) || isIos){
|
||||
globalThis.polyfilledDragDrop = true
|
||||
dragPolyfill({
|
||||
// use this to make use of the scroll behaviour
|
||||
dragImageTranslateOverride: scrollBehaviourDragImageTranslateOverride,
|
||||
// holdToDrag: 400,
|
||||
forceApply: true
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
const rfdcClone = rfdc({
|
||||
circles:false,
|
||||
})
|
||||
function safeStructuredClone<T>(data:T):T{
|
||||
try {
|
||||
return structuredClone(data)
|
||||
} catch (error) {
|
||||
return rfdcClone(data)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const testDom = document.createElement('div');
|
||||
const supports = ('draggable' in testDom) || ('ondragstart' in testDom && 'ondrop' in testDom);
|
||||
const isIos = navigator.userAgent ? (!!navigator.userAgent.match('iPhone OS') || !!navigator.userAgent.match('iPad')) : false
|
||||
testDom.remove()
|
||||
|
||||
if((!supports) || isIos){
|
||||
globalThis.polyfilledDragDrop = true
|
||||
dragPolyfill({
|
||||
// use this to make use of the scroll behaviour
|
||||
dragImageTranslateOverride: scrollBehaviourDragImageTranslateOverride,
|
||||
// holdToDrag: 400,
|
||||
forceApply: true
|
||||
});
|
||||
}
|
||||
globalThis.Buffer = BufferPolyfill
|
||||
//@ts-ignore
|
||||
globalThis.WritableStream = globalThis.WritableStream ?? WritableStream
|
||||
globalThis.ReadableStream = globalThis.ReadableStream ?? ReadableStream
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
globalThis.safeStructuredClone = safeStructuredClone
|
||||
|
||||
globalThis.Buffer = BufferPolyfill
|
||||
//@ts-ignore
|
||||
globalThis.WritableStream = globalThis.WritableStream ?? WritableStream
|
||||
//@ts-ignore
|
||||
globalThis.ReadableStream = globalThis.ReadableStream ?? ReadableStream
|
||||
//@ts-ignore
|
||||
globalThis.TransformStream = globalThis.TransformStream ?? TransformStream
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase, setDatabase } from "../storage/database";
|
||||
import { CurrentCharacter, CurrentChat, selectedCharID } from "../stores";
|
||||
import { getCurrentCharacter, getCurrentChat, getDatabase, setCurrentChat, setDatabase } from "../storage/database.svelte";
|
||||
import { selectedCharID } from "../stores.svelte";
|
||||
import { alertInput, alertMd, alertNormal, alertSelect, alertToast } from "../alert";
|
||||
import { sayTTS } from "./tts";
|
||||
import { risuChatParser } from "../parser";
|
||||
import { sendChat } from ".";
|
||||
import { loadLoreBookV3Prompt } from "./lorebook";
|
||||
import { risuChatParser } from "../parser.svelte";
|
||||
import { sendChat } from "./index.svelte";
|
||||
import { loadLoreBookV3Prompt } from "./lorebook.svelte";
|
||||
import { runTrigger } from "./triggers";
|
||||
|
||||
export async function processMultiCommand(command:string) {
|
||||
@@ -40,7 +40,7 @@ export async function processMultiCommand(command:string) {
|
||||
|
||||
|
||||
async function processCommand(command:string, pipe:string):Promise<false | string>{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const currentChar = db.characters[get(selectedCharID)]
|
||||
const currentChat = currentChar.chats[currentChar.chatPage]
|
||||
let {commandName, arg, namedArg} = commandParser(command, pipe)
|
||||
@@ -180,7 +180,7 @@ async function processCommand(command:string, pipe:string):Promise<false | strin
|
||||
}
|
||||
case 'setvar':{
|
||||
console.log(namedArg, arg)
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
const chat = char.chats[char.chatPage]
|
||||
@@ -194,7 +194,7 @@ async function processCommand(command:string, pipe:string):Promise<false | strin
|
||||
return ''
|
||||
}
|
||||
case 'addvar':{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
const chat = char.chats[char.chatPage]
|
||||
@@ -207,7 +207,7 @@ async function processCommand(command:string, pipe:string):Promise<false | strin
|
||||
return ''
|
||||
}
|
||||
case 'getvar':{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
const chat = char.chats[char.chatPage]
|
||||
@@ -222,17 +222,17 @@ async function processCommand(command:string, pipe:string):Promise<false | strin
|
||||
return JSON.stringify(p)
|
||||
}
|
||||
case 'trigger':{
|
||||
const currentChar = get(CurrentCharacter)
|
||||
const currentChar = getCurrentCharacter()
|
||||
if(currentChar.type === 'group'){
|
||||
return;
|
||||
}
|
||||
const triggerResult = await runTrigger(currentChar, 'manual', {
|
||||
chat: get(CurrentChat),
|
||||
chat: getCurrentChat(),
|
||||
manualName: arg
|
||||
});
|
||||
|
||||
if(triggerResult){
|
||||
CurrentChat.set(triggerResult.chat);
|
||||
setCurrentChat(triggerResult.chat);
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import { DataBase, type Chat, type character } from "src/ts/storage/database";
|
||||
import { getDatabase, type Chat, type character } from "src/ts/storage/database.svelte";
|
||||
import { HypaProcesser } from '../memory/hypamemory'
|
||||
import type { OpenAIChat } from "..";
|
||||
import { stringlizeChat } from "../stringlize";
|
||||
import { get } from "svelte/store";
|
||||
import { getUserName } from "src/ts/util";
|
||||
|
||||
export async function additionalInformations(char: character,chats:Chat,){
|
||||
const processer = new HypaProcesser('MiniLM')
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
|
||||
const info = char.additionalText
|
||||
if(info){
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { OpenAIChat } from ".";
|
||||
import type { character } from "../storage/database";
|
||||
import type { OpenAIChat } from "./index.svelte";
|
||||
import type { character } from "../storage/database.svelte";
|
||||
import { risuChatParser } from "./scripts";
|
||||
|
||||
export function exampleMessage(char:character, userName:string):OpenAIChat[]{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import localforage from "localforage";
|
||||
import { selectSingleFile } from "../../util";
|
||||
import { v4 } from "uuid";
|
||||
import { DataBase } from "../../storage/database";
|
||||
import { get } from "svelte/store";
|
||||
import { checkImageType } from "../../parser";
|
||||
import { getDatabase } from "../../storage/database.svelte";
|
||||
import { checkImageType } from "../../parser.svelte";
|
||||
|
||||
const inlayStorage = localforage.createInstance({
|
||||
name: 'inlay',
|
||||
@@ -85,7 +83,7 @@ export async function getInlayImage(id: string){
|
||||
}
|
||||
|
||||
export function supportsInlayImage(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
return db.aiModel.startsWith('gptv') || db.aiModel === 'gemini-pro-vision' || db.aiModel.startsWith('claude-3') || db.aiModel.startsWith('gpt4_turbo') || db.aiModel.startsWith('gpt5') || db.aiModel.startsWith('gpt4o') ||
|
||||
(db.aiModel === 'reverse_proxy' && (
|
||||
db.proxyRequestModel?.startsWith('gptv') || db.proxyRequestModel === 'gemini-pro-vision' || db.proxyRequestModel?.startsWith('claude-3') || db.proxyRequestModel.startsWith('gpt4_turbo') ||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { DataBase, setDatabase } from 'src/ts/storage/database';
|
||||
import { selectedCharID } from 'src/ts/stores';
|
||||
import { getDatabase, setDatabase } from 'src/ts/storage/database.svelte';
|
||||
import { selectedCharID } from 'src/ts/stores.svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import { doingChat, sendChat } from '..';
|
||||
import { downloadFile, isTauri } from 'src/ts/storage/globalApi';
|
||||
import { doingChat, sendChat } from '../index.svelte';
|
||||
import { downloadFile, isTauri } from 'src/ts/globalApi.svelte';
|
||||
import { HypaProcesser } from '../memory/hypamemory';
|
||||
import { BufferToText as BufferToText, selectSingleFile, sleep } from 'src/ts/util';
|
||||
import { postInlayImage } from './image';
|
||||
@@ -19,7 +19,7 @@ async function sendPofile(arg:sendFileArg){
|
||||
let note = ''
|
||||
let speaker = ''
|
||||
let parseMode = 0
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let currentChar = db.characters[get(selectedCharID)]
|
||||
let currentChat = currentChar.chats[currentChar.chatPage]
|
||||
const lines = arg.file.split('\n')
|
||||
|
||||
@@ -3,11 +3,11 @@ import { findCharacterbyId } from "../util";
|
||||
import { alertConfirm, alertError, alertSelectChar } from "../alert";
|
||||
import { language } from "src/lang";
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase, setDatabase } from "../storage/database";
|
||||
import { selectedCharID } from "../stores";
|
||||
import { getDatabase, setDatabase } from "../storage/database.svelte";
|
||||
import { selectedCharID } from "../stores.svelte";
|
||||
|
||||
export async function addGroupChar(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let selectedId = get(selectedCharID)
|
||||
let group = db.characters[selectedId]
|
||||
if(group.type === 'group'){
|
||||
@@ -36,7 +36,7 @@ export async function addGroupChar(){
|
||||
|
||||
|
||||
export function rmCharFromGroup(index:number){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let selectedId = get(selectedCharID)
|
||||
let group = db.characters[selectedId]
|
||||
if(group.type === 'group'){
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { get, writable } from "svelte/store";
|
||||
import { DataBase, setDatabase, type character, type MessageGenerationInfo, type Chat } from "../storage/database";
|
||||
import { CharEmotion, selectedCharID } from "../stores";
|
||||
import { type character, type MessageGenerationInfo, type Chat } from "../storage/database.svelte";
|
||||
import { DBState } from '../stores.svelte';
|
||||
import { CharEmotion, selectedCharID } from "../stores.svelte";
|
||||
import { ChatTokenizer, tokenize, tokenizeNum } from "../tokenizer";
|
||||
import { language } from "../../lang";
|
||||
import { alertError } from "../alert";
|
||||
import { loadLoreBookPrompt, loadLoreBookV3Prompt } from "./lorebook";
|
||||
import { loadLoreBookV3Prompt } from "./lorebook.svelte";
|
||||
import { findCharacterbyId, getAuthorNoteDefaultText, getPersonaPrompt, getUserName, isLastCharPunctuation, trimUntilPunctuation } from "../util";
|
||||
import { requestChatData } from "./request";
|
||||
import { stableDiff } from "./stableDiff";
|
||||
@@ -120,10 +121,9 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
chatProcessStage.set(0)
|
||||
}
|
||||
|
||||
let db = get(DataBase)
|
||||
db.statics.messages += 1
|
||||
DBState.db.statics.messages += 1
|
||||
let selectedChar = get(selectedCharID)
|
||||
const nowChatroom = db.characters[selectedChar]
|
||||
const nowChatroom = DBState.db.characters[selectedChar]
|
||||
nowChatroom.lastInteraction = Date.now()
|
||||
let selectedChat = nowChatroom.chatPage
|
||||
nowChatroom.chats[nowChatroom.chatPage].message = nowChatroom.chats[nowChatroom.chatPage].message.map((v) => {
|
||||
@@ -134,7 +134,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
|
||||
let currentChar:character
|
||||
let caculatedChatTokens = 0
|
||||
if(db.aiModel.startsWith('gpt')){
|
||||
if(DBState.db.aiModel.startsWith('gpt')){
|
||||
caculatedChatTokens += 5
|
||||
}
|
||||
else{
|
||||
@@ -188,27 +188,27 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
|
||||
let chatAdditonalTokens = arg.chatAdditonalTokens ?? caculatedChatTokens
|
||||
const tokenizer = new ChatTokenizer(chatAdditonalTokens, db.aiModel.startsWith('gpt') ? 'noName' : 'name')
|
||||
const tokenizer = new ChatTokenizer(chatAdditonalTokens, DBState.db.aiModel.startsWith('gpt') ? 'noName' : 'name')
|
||||
let currentChat = runCurrentChatFunction(nowChatroom.chats[selectedChat])
|
||||
nowChatroom.chats[selectedChat] = currentChat
|
||||
let maxContextTokens = db.maxContext
|
||||
let maxContextTokens = DBState.db.maxContext
|
||||
|
||||
if(db.aiModel === 'gpt35'){
|
||||
if(DBState.db.aiModel === 'gpt35'){
|
||||
if(maxContextTokens > 4000){
|
||||
maxContextTokens = 4000
|
||||
}
|
||||
}
|
||||
if(db.aiModel === 'gpt35_16k' || db.aiModel === 'gpt35_16k_0613'){
|
||||
if(DBState.db.aiModel === 'gpt35_16k' || DBState.db.aiModel === 'gpt35_16k_0613'){
|
||||
if(maxContextTokens > 16000){
|
||||
maxContextTokens = 16000
|
||||
}
|
||||
}
|
||||
if(db.aiModel === 'gpt4'){
|
||||
if(DBState.db.aiModel === 'gpt4'){
|
||||
if(maxContextTokens > 8000){
|
||||
maxContextTokens = 8000
|
||||
}
|
||||
}
|
||||
if(db.aiModel === 'deepai'){
|
||||
if(DBState.db.aiModel === 'deepai'){
|
||||
if(maxContextTokens > 3000){
|
||||
maxContextTokens = 3000
|
||||
}
|
||||
@@ -229,7 +229,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
'personaPrompt':([] as OpenAIChat[])
|
||||
}
|
||||
|
||||
let promptTemplate = structuredClone(db.promptTemplate)
|
||||
let promptTemplate = safeStructuredClone(DBState.db.promptTemplate)
|
||||
const usingPromptTemplate = !!promptTemplate
|
||||
if(promptTemplate){
|
||||
let hasPostEverything = false
|
||||
@@ -246,7 +246,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
})
|
||||
}
|
||||
}
|
||||
if(currentChar.utilityBot && (!(usingPromptTemplate && db.promptSettings.utilOverride))){
|
||||
if(currentChar.utilityBot && (!(usingPromptTemplate && DBState.db.promptSettings.utilOverride))){
|
||||
promptTemplate = [
|
||||
{
|
||||
"type": "plain",
|
||||
@@ -278,7 +278,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
|
||||
if((!currentChar.utilityBot) && (!promptTemplate)){
|
||||
const mainp = currentChar.systemPrompt?.replaceAll('{{original}}', db.mainPrompt) || db.mainPrompt
|
||||
const mainp = currentChar.systemPrompt?.replaceAll('{{original}}', DBState.db.mainPrompt) || DBState.db.mainPrompt
|
||||
|
||||
|
||||
function formatPrompt(data:string){
|
||||
@@ -300,13 +300,13 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
return chatObjects;
|
||||
}
|
||||
|
||||
unformated.main.push(...formatPrompt(risuChatParser(mainp + ((db.additionalPrompt === '' || (!db.promptPreprocess)) ? '' : `\n${db.additionalPrompt}`), {chara: currentChar})))
|
||||
unformated.main.push(...formatPrompt(risuChatParser(mainp + ((DBState.db.additionalPrompt === '' || (!DBState.db.promptPreprocess)) ? '' : `\n${DBState.db.additionalPrompt}`), {chara: currentChar})))
|
||||
|
||||
if(db.jailbreakToggle){
|
||||
unformated.jailbreak.push(...formatPrompt(risuChatParser(db.jailbreak, {chara: currentChar})))
|
||||
if(DBState.db.jailbreakToggle){
|
||||
unformated.jailbreak.push(...formatPrompt(risuChatParser(DBState.db.jailbreak, {chara: currentChar})))
|
||||
}
|
||||
|
||||
unformated.globalNote.push(...formatPrompt(risuChatParser(currentChar.replaceGlobalNote?.replaceAll('{{original}}', db.globalNote) || db.globalNote, {chara:currentChar})))
|
||||
unformated.globalNote.push(...formatPrompt(risuChatParser(currentChar.replaceGlobalNote?.replaceAll('{{original}}', DBState.db.globalNote) || DBState.db.globalNote, {chara:currentChar})))
|
||||
}
|
||||
|
||||
if(currentChat.note){
|
||||
@@ -322,7 +322,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
})
|
||||
}
|
||||
|
||||
if(db.chainOfThought && (!(usingPromptTemplate && db.promptSettings.customChainOfThought))){
|
||||
if(DBState.db.chainOfThought && (!(usingPromptTemplate && DBState.db.promptSettings.customChainOfThought))){
|
||||
unformated.postEverything.push({
|
||||
role: 'system',
|
||||
content: `<instruction> - before respond everything, Think step by step as a ai assistant how would you respond inside <Thoughts> xml tag. this must be less than 5 paragraphs.</instruction>`
|
||||
@@ -330,7 +330,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
|
||||
{
|
||||
let description = risuChatParser((db.promptPreprocess ? db.descriptionPrefix: '') + currentChar.desc, {chara: currentChar})
|
||||
let description = risuChatParser((DBState.db.promptPreprocess ? DBState.db.descriptionPrefix: '') + currentChar.desc, {chara: currentChar})
|
||||
|
||||
const additionalInfo = await additionalInformations(currentChar, currentChat)
|
||||
|
||||
@@ -390,7 +390,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
}
|
||||
|
||||
if(db.personaPrompt){
|
||||
if(DBState.db.personaPrompt){
|
||||
unformated.personaPrompt.push({
|
||||
role: 'system',
|
||||
content: risuChatParser(getPersonaPrompt(), {chara: currentChar})
|
||||
@@ -434,7 +434,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
|
||||
//await tokenize currernt
|
||||
let currentTokens = db.maxResponse
|
||||
let currentTokens = DBState.db.maxResponse
|
||||
let supaMemoryCardUsed = false
|
||||
|
||||
//for unexpected error
|
||||
@@ -466,7 +466,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
for(const card of template){
|
||||
switch(card.type){
|
||||
case 'persona':{
|
||||
let pmt = structuredClone(unformated.personaPrompt)
|
||||
let pmt = safeStructuredClone(unformated.personaPrompt)
|
||||
if(card.innerFormat && pmt.length > 0){
|
||||
for(let i=0;i<pmt.length;i++){
|
||||
pmt[i].content = risuChatParser(positionParser(card.innerFormat), {chara: currentChar}).replace('{{slot}}', pmt[i].content)
|
||||
@@ -477,7 +477,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
break
|
||||
}
|
||||
case 'description':{
|
||||
let pmt = structuredClone(unformated.description)
|
||||
let pmt = safeStructuredClone(unformated.description)
|
||||
if(card.innerFormat && pmt.length > 0){
|
||||
for(let i=0;i<pmt.length;i++){
|
||||
pmt[i].content = risuChatParser(positionParser(card.innerFormat), {chara: currentChar}).replace('{{slot}}', pmt[i].content)
|
||||
@@ -488,7 +488,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
break
|
||||
}
|
||||
case 'authornote':{
|
||||
let pmt = structuredClone(unformated.authorNote)
|
||||
let pmt = safeStructuredClone(unformated.authorNote)
|
||||
if(card.innerFormat && pmt.length > 0){
|
||||
for(let i=0;i<pmt.length;i++){
|
||||
pmt[i].content = risuChatParser(positionParser(card.innerFormat), {chara: currentChar}).replace('{{slot}}', pmt[i].content || card.defaultText || '')
|
||||
@@ -504,10 +504,10 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
case 'postEverything':{
|
||||
await tokenizeChatArray(unformated.postEverything)
|
||||
if(usingPromptTemplate && db.promptSettings.postEndInnerFormat){
|
||||
if(usingPromptTemplate && DBState.db.promptSettings.postEndInnerFormat){
|
||||
await tokenizeChatArray([{
|
||||
role: 'system',
|
||||
content: db.promptSettings.postEndInnerFormat
|
||||
content: DBState.db.promptSettings.postEndInnerFormat
|
||||
}])
|
||||
}
|
||||
break
|
||||
@@ -515,10 +515,10 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
case 'plain':
|
||||
case 'jailbreak':
|
||||
case 'cot':{
|
||||
if((!db.jailbreakToggle) && (card.type === 'jailbreak')){
|
||||
if((!DBState.db.jailbreakToggle) && (card.type === 'jailbreak')){
|
||||
continue
|
||||
}
|
||||
if((!db.chainOfThought) && (card.type === 'cot')){
|
||||
if((!DBState.db.chainOfThought) && (card.type === 'cot')){
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -573,7 +573,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
let chats = unformated.chats.slice(start, end)
|
||||
|
||||
if(usingPromptTemplate && db.promptSettings.sendChatAsSystem && (!card.chatAsOriginalOnSystem)){
|
||||
if(usingPromptTemplate && DBState.db.promptSettings.sendChatAsSystem && (!card.chatAsOriginalOnSystem)){
|
||||
chats = systemizeChat(chats)
|
||||
}
|
||||
await tokenizeChatArray(chats)
|
||||
@@ -603,7 +603,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
|
||||
let chats:OpenAIChat[] = examples
|
||||
|
||||
if(!db.aiModel.startsWith('novelai')){
|
||||
if(!DBState.db.aiModel.startsWith('novelai')){
|
||||
chats.push({
|
||||
role: 'system',
|
||||
content: '[Start a new chat]',
|
||||
@@ -621,7 +621,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
'editprocess'))
|
||||
}
|
||||
|
||||
if(usingPromptTemplate && db.promptSettings.sendName){
|
||||
if(usingPromptTemplate && DBState.db.promptSettings.sendName){
|
||||
chat.content = `${currentChar.name}: ${chat.content}`
|
||||
chat.attr = ['nameAdded']
|
||||
}
|
||||
@@ -699,20 +699,35 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
|
||||
let attr:string[] = []
|
||||
let role:'user'|'assistant'|'system' = msg.role === 'user' ? 'user' : 'assistant'
|
||||
|
||||
if(nowChatroom.type === 'group' || (usingPromptTemplate && db.promptSettings.sendName)){
|
||||
formatedChat = name + ': ' + formatedChat
|
||||
attr.push('nameAdded')
|
||||
if(
|
||||
(nowChatroom.type === 'group' && findCharacterbyIdwithCache(msg.saying).chaId !== currentChar.chaId) ||
|
||||
(nowChatroom.type === 'group' && DBState.db.groupOtherBotRole === 'assistant') ||
|
||||
(usingPromptTemplate && DBState.db.promptSettings.sendName)
|
||||
){
|
||||
const form = DBState.db.groupTemplate || `<{{char}}\'s Message>\n{{slot}}\n</{{char}}\'s Message>`
|
||||
formatedChat = risuChatParser(form, {chara: findCharacterbyIdwithCache(msg.saying).name}).replace('{{slot}}', formatedChat)
|
||||
switch(DBState.db.groupOtherBotRole){
|
||||
case 'user':
|
||||
case 'assistant':
|
||||
case 'system':
|
||||
role = DBState.db.groupOtherBotRole
|
||||
break
|
||||
default:
|
||||
role = 'assistant'
|
||||
break
|
||||
}
|
||||
}
|
||||
if(usingPromptTemplate && db.promptSettings.maxThoughtTagDepth !== -1){
|
||||
if(usingPromptTemplate && DBState.db.promptSettings.maxThoughtTagDepth !== -1){
|
||||
const depth = ms.length - index
|
||||
if(depth >= db.promptSettings.maxThoughtTagDepth){
|
||||
if(depth >= DBState.db.promptSettings.maxThoughtTagDepth){
|
||||
formatedChat = formatedChat.replace(/<Thoughts>(.+?)<\/Thoughts>/gm, '')
|
||||
}
|
||||
}
|
||||
|
||||
const chat:OpenAIChat = {
|
||||
role: msg.role === 'user' ? 'user' : 'assistant',
|
||||
role: role,
|
||||
content: formatedChat,
|
||||
memo: msg.chatId,
|
||||
attr: attr,
|
||||
@@ -725,6 +740,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
currentTokens += await tokenizer.tokenizeChat(chat)
|
||||
index++
|
||||
}
|
||||
console.log(JSON.stringify(chats, null, 2))
|
||||
|
||||
const depthPrompts = lorepmt.actives.filter(v => {
|
||||
return (v.pos === 'depth' && v.depth > 0) || v.pos === 'reverse_depth'
|
||||
@@ -738,9 +754,9 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
currentTokens += await tokenizer.tokenizeChat(chat)
|
||||
}
|
||||
|
||||
if(nowChatroom.supaMemory && (db.supaModelType !== 'none' || db.hanuraiEnable || db.hypav2)){
|
||||
if(nowChatroom.supaMemory && (DBState.db.supaModelType !== 'none' || DBState.db.hanuraiEnable || DBState.db.hypav2)){
|
||||
chatProcessStage.set(2)
|
||||
if(db.hanuraiEnable){
|
||||
if(DBState.db.hanuraiEnable){
|
||||
const hn = await hanuraiMemory(chats, {
|
||||
currentTokens,
|
||||
maxContextTokens,
|
||||
@@ -754,7 +770,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
chats = hn.chats
|
||||
currentTokens = hn.tokens
|
||||
}
|
||||
else if(db.hypav2){ //HypaV2 support needs to be changed like this.
|
||||
else if(DBState.db.hypav2){ //HypaV2 support needs to be changed like this.
|
||||
const sp = await hypaMemoryV2(chats, currentTokens, maxContextTokens, currentChat, nowChatroom, tokenizer)
|
||||
console.log("All chats: ", chats)
|
||||
if(sp.error){
|
||||
@@ -765,13 +781,12 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
chats = sp.chats
|
||||
currentTokens = sp.currentTokens
|
||||
currentChat.hypaV2Data = sp.memory ?? currentChat.hypaV2Data
|
||||
db.characters[selectedChar].chats[selectedChat].hypaV2Data = currentChat.hypaV2Data
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].hypaV2Data = currentChat.hypaV2Data
|
||||
console.log(currentChat.hypaV2Data)
|
||||
DataBase.set(db)
|
||||
}
|
||||
else{
|
||||
const sp = await supaMemory(chats, currentTokens, maxContextTokens, currentChat, nowChatroom, tokenizer, {
|
||||
asHyper: db.hypaMemory
|
||||
asHyper: DBState.db.hypaMemory
|
||||
})
|
||||
if(sp.error){
|
||||
alertError(sp.error)
|
||||
@@ -780,9 +795,8 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
chats = sp.chats
|
||||
currentTokens = sp.currentTokens
|
||||
currentChat.supaMemoryData = sp.memory ?? currentChat.supaMemoryData
|
||||
db.characters[selectedChar].chats[selectedChat].supaMemoryData = currentChat.supaMemoryData
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].supaMemoryData = currentChat.supaMemoryData
|
||||
console.log(currentChat.supaMemoryData)
|
||||
DataBase.set(db)
|
||||
currentChat.lastMemory = sp.lastId ?? currentChat.lastMemory;
|
||||
}
|
||||
chatProcessStage.set(1)
|
||||
@@ -801,7 +815,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
currentChat.lastMemory = chats[0].memo
|
||||
}
|
||||
|
||||
let biases:[string,number][] = db.bias.concat(currentChar.bias).map((v) => {
|
||||
let biases:[string,number][] = DBState.db.bias.concat(currentChar.bias).map((v) => {
|
||||
return [risuChatParser(v[0].replaceAll("\\n","\n").replaceAll("\\r","\r").replaceAll("\\\\","\\"), {chara: currentChar}),v[1]]
|
||||
})
|
||||
|
||||
@@ -867,13 +881,13 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
//make into one
|
||||
|
||||
let formated:OpenAIChat[] = []
|
||||
const formatOrder = structuredClone(db.formatingOrder)
|
||||
const formatOrder = safeStructuredClone(DBState.db.formatingOrder)
|
||||
if(formatOrder){
|
||||
formatOrder.push('postEverything')
|
||||
}
|
||||
|
||||
//continue chat model
|
||||
if(arg.continue && (db.aiModel.startsWith('claude') || db.aiModel.startsWith('gpt') || db.aiModel.startsWith('openrouter') || db.aiModel.startsWith('reverse_proxy'))){
|
||||
if(arg.continue && (DBState.db.aiModel.startsWith('claude') || DBState.db.aiModel.startsWith('gpt') || DBState.db.aiModel.startsWith('openrouter') || DBState.db.aiModel.startsWith('reverse_proxy'))){
|
||||
unformated.postEverything.push({
|
||||
role: 'system',
|
||||
content: '[Continue the last response]'
|
||||
@@ -885,7 +899,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
if(!chat.content.trim()){
|
||||
continue
|
||||
}
|
||||
if(!(db.aiModel.startsWith('gpt') || db.aiModel.startsWith('claude') || db.aiModel === 'openrouter' || db.aiModel === 'reverse_proxy')){
|
||||
if(!(DBState.db.aiModel.startsWith('gpt') || DBState.db.aiModel.startsWith('claude') || DBState.db.aiModel === 'openrouter' || DBState.db.aiModel === 'reverse_proxy')){
|
||||
formated.push(chat)
|
||||
continue
|
||||
}
|
||||
@@ -911,7 +925,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
for(const card of template){
|
||||
switch(card.type){
|
||||
case 'persona':{
|
||||
let pmt = structuredClone(unformated.personaPrompt)
|
||||
let pmt = safeStructuredClone(unformated.personaPrompt)
|
||||
if(card.innerFormat && pmt.length > 0){
|
||||
for(let i=0;i<pmt.length;i++){
|
||||
pmt[i].content = risuChatParser(positionParser(card.innerFormat), {chara: currentChar}).replace('{{slot}}', pmt[i].content)
|
||||
@@ -922,7 +936,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
break
|
||||
}
|
||||
case 'description':{
|
||||
let pmt = structuredClone(unformated.description)
|
||||
let pmt = safeStructuredClone(unformated.description)
|
||||
if(card.innerFormat && pmt.length > 0){
|
||||
for(let i=0;i<pmt.length;i++){
|
||||
pmt[i].content = risuChatParser(positionParser(card.innerFormat), {chara: currentChar}).replace('{{slot}}', pmt[i].content)
|
||||
@@ -933,7 +947,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
break
|
||||
}
|
||||
case 'authornote':{
|
||||
let pmt = structuredClone(unformated.authorNote)
|
||||
let pmt = safeStructuredClone(unformated.authorNote)
|
||||
if(card.innerFormat && pmt.length > 0){
|
||||
for(let i=0;i<pmt.length;i++){
|
||||
pmt[i].content = risuChatParser(positionParser(card.innerFormat), {chara: currentChar}).replace('{{slot}}', pmt[i].content || card.defaultText || '')
|
||||
@@ -949,10 +963,10 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
case 'postEverything':{
|
||||
pushPrompts(unformated.postEverything)
|
||||
if(usingPromptTemplate && db.promptSettings.postEndInnerFormat){
|
||||
if(usingPromptTemplate && DBState.db.promptSettings.postEndInnerFormat){
|
||||
pushPrompts([{
|
||||
role: 'system',
|
||||
content: db.promptSettings.postEndInnerFormat
|
||||
content: DBState.db.promptSettings.postEndInnerFormat
|
||||
}])
|
||||
}
|
||||
break
|
||||
@@ -960,10 +974,10 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
case 'plain':
|
||||
case 'jailbreak':
|
||||
case 'cot':{
|
||||
if((!db.jailbreakToggle) && (card.type === 'jailbreak')){
|
||||
if((!DBState.db.jailbreakToggle) && (card.type === 'jailbreak')){
|
||||
continue
|
||||
}
|
||||
if((!db.chainOfThought) && (card.type === 'cot')){
|
||||
if((!DBState.db.chainOfThought) && (card.type === 'cot')){
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1018,14 +1032,14 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
|
||||
let chats = unformated.chats.slice(start, end)
|
||||
if(usingPromptTemplate && db.promptSettings.sendChatAsSystem && (!card.chatAsOriginalOnSystem)){
|
||||
if(usingPromptTemplate && DBState.db.promptSettings.sendChatAsSystem && (!card.chatAsOriginalOnSystem)){
|
||||
chats = systemizeChat(chats)
|
||||
}
|
||||
pushPrompts(chats)
|
||||
break
|
||||
}
|
||||
case 'memory':{
|
||||
let pmt = structuredClone(memories)
|
||||
let pmt = safeStructuredClone(memories)
|
||||
if(card.innerFormat && pmt.length > 0){
|
||||
for(let i=0;i<pmt.length;i++){
|
||||
pmt[i].content = risuChatParser(card.innerFormat, {chara: currentChar}).replace('{{slot}}', pmt[i].content)
|
||||
@@ -1094,7 +1108,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
|
||||
//estimate tokens
|
||||
let outputTokens = db.maxResponse
|
||||
let outputTokens = DBState.db.maxResponse
|
||||
if(inputTokens + outputTokens > maxContextTokens){
|
||||
outputTokens = maxContextTokens - inputTokens
|
||||
}
|
||||
@@ -1138,14 +1152,14 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
else if(req.type === 'streaming'){
|
||||
const reader = req.result.getReader()
|
||||
let msgIndex = db.characters[selectedChar].chats[selectedChat].message.length
|
||||
let msgIndex = DBState.db.characters[selectedChar].chats[selectedChat].message.length
|
||||
let prefix = ''
|
||||
if(arg.continue){
|
||||
msgIndex -= 1
|
||||
prefix = db.characters[selectedChar].chats[selectedChat].message[msgIndex].data
|
||||
prefix = DBState.db.characters[selectedChar].chats[selectedChat].message[msgIndex].data
|
||||
}
|
||||
else{
|
||||
db.characters[selectedChar].chats[selectedChat].message.push({
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].message.push({
|
||||
role: 'char',
|
||||
data: "",
|
||||
saying: currentChar.chaId,
|
||||
@@ -1153,7 +1167,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
generationInfo,
|
||||
})
|
||||
}
|
||||
db.characters[selectedChar].chats[selectedChat].isStreaming = true
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].isStreaming = true
|
||||
let lastResponseChunk:{[key:string]:string} = {}
|
||||
while(abortSignal.aborted === false){
|
||||
const readed = (await reader.read())
|
||||
@@ -1164,27 +1178,25 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
if(!result){
|
||||
result = ''
|
||||
}
|
||||
if(db.removeIncompleteResponse){
|
||||
if(DBState.db.removeIncompleteResponse){
|
||||
result = trimUntilPunctuation(result)
|
||||
}
|
||||
let result2 = await processScriptFull(nowChatroom, reformatContent(prefix + result), 'editoutput', msgIndex)
|
||||
db.characters[selectedChar].chats[selectedChat].message[msgIndex].data = result2.data
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].message[msgIndex].data = result2.data
|
||||
emoChanged = result2.emoChanged
|
||||
db.characters[selectedChar].reloadKeys += 1
|
||||
setDatabase(db)
|
||||
DBState.db.characters[selectedChar].reloadKeys += 1
|
||||
}
|
||||
if(readed.done){
|
||||
db.characters[selectedChar].chats[selectedChat].isStreaming = false
|
||||
db.characters[selectedChar].reloadKeys += 1
|
||||
setDatabase(db)
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].isStreaming = false
|
||||
DBState.db.characters[selectedChar].reloadKeys += 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
addRerolls(generationId, Object.values(lastResponseChunk))
|
||||
|
||||
db.characters[selectedChar].chats[selectedChat] = runCurrentChatFunction(db.characters[selectedChar].chats[selectedChat])
|
||||
currentChat = db.characters[selectedChar].chats[selectedChat]
|
||||
DBState.db.characters[selectedChar].chats[selectedChat] = runCurrentChatFunction(DBState.db.characters[selectedChar].chats[selectedChat])
|
||||
currentChat = DBState.db.characters[selectedChar].chats[selectedChat]
|
||||
const triggerResult = await runTrigger(currentChar, 'output', {chat:currentChat})
|
||||
if(triggerResult && triggerResult.chat){
|
||||
currentChat = triggerResult.chat
|
||||
@@ -1194,15 +1206,13 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
const inlayr = runInlayScreen(currentChar, currentChat.message[msgIndex].data)
|
||||
currentChat.message[msgIndex].data = inlayr.text
|
||||
db.characters[selectedChar].chats[selectedChat] = currentChat
|
||||
setDatabase(db)
|
||||
DBState.db.characters[selectedChar].chats[selectedChat] = currentChat
|
||||
if(inlayr.promise){
|
||||
const t = await inlayr.promise
|
||||
currentChat.message[msgIndex].data = t
|
||||
db.characters[selectedChar].chats[selectedChat] = currentChat
|
||||
setDatabase(db)
|
||||
DBState.db.characters[selectedChar].chats[selectedChat] = currentChat
|
||||
}
|
||||
if(db.ttsAutoSpeech){
|
||||
if(DBState.db.ttsAutoSpeech){
|
||||
await sayTTS(currentChar, result)
|
||||
}
|
||||
}
|
||||
@@ -1214,14 +1224,14 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
for(let i=0;i<msgs.length;i++){
|
||||
let msg = msgs[i]
|
||||
let mess = msg[1]
|
||||
let msgIndex = db.characters[selectedChar].chats[selectedChat].message.length
|
||||
let msgIndex = DBState.db.characters[selectedChar].chats[selectedChat].message.length
|
||||
let result2 = await processScriptFull(nowChatroom, reformatContent(mess), 'editoutput', msgIndex)
|
||||
if(i === 0 && arg.continue){
|
||||
msgIndex -= 1
|
||||
let beforeChat = db.characters[selectedChar].chats[selectedChat].message[msgIndex]
|
||||
let beforeChat = DBState.db.characters[selectedChar].chats[selectedChat].message[msgIndex]
|
||||
result2 = await processScriptFull(nowChatroom, reformatContent(beforeChat.data + mess), 'editoutput', msgIndex)
|
||||
}
|
||||
if(db.removeIncompleteResponse){
|
||||
if(DBState.db.removeIncompleteResponse){
|
||||
result2.data = trimUntilPunctuation(result2.data)
|
||||
}
|
||||
result = result2.data
|
||||
@@ -1229,7 +1239,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
result = inlayResult.text
|
||||
emoChanged = result2.emoChanged
|
||||
if(i === 0 && arg.continue){
|
||||
db.characters[selectedChar].chats[selectedChat].message[msgIndex] = {
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].message[msgIndex] = {
|
||||
role: 'char',
|
||||
data: result,
|
||||
saying: currentChar.chaId,
|
||||
@@ -1238,45 +1248,43 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
}
|
||||
if(inlayResult.promise){
|
||||
const p = await inlayResult.promise
|
||||
db.characters[selectedChar].chats[selectedChat].message[msgIndex].data = p
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].message[msgIndex].data = p
|
||||
}
|
||||
}
|
||||
else if(i===0){
|
||||
db.characters[selectedChar].chats[selectedChat].message.push({
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].message.push({
|
||||
role: msg[0],
|
||||
data: result,
|
||||
saying: currentChar.chaId,
|
||||
time: Date.now(),
|
||||
generationInfo
|
||||
})
|
||||
const ind = db.characters[selectedChar].chats[selectedChat].message.length - 1
|
||||
const ind = DBState.db.characters[selectedChar].chats[selectedChat].message.length - 1
|
||||
if(inlayResult.promise){
|
||||
const p = await inlayResult.promise
|
||||
db.characters[selectedChar].chats[selectedChat].message[ind].data = p
|
||||
DBState.db.characters[selectedChar].chats[selectedChat].message[ind].data = p
|
||||
}
|
||||
mrerolls.push(result)
|
||||
}
|
||||
else{
|
||||
mrerolls.push(result)
|
||||
}
|
||||
db.characters[selectedChar].reloadKeys += 1
|
||||
if(db.ttsAutoSpeech){
|
||||
DBState.db.characters[selectedChar].reloadKeys += 1
|
||||
if(DBState.db.ttsAutoSpeech){
|
||||
await sayTTS(currentChar, result)
|
||||
}
|
||||
setDatabase(db)
|
||||
}
|
||||
|
||||
if(mrerolls.length >1){
|
||||
addRerolls(generationId, mrerolls)
|
||||
}
|
||||
|
||||
db.characters[selectedChar].chats[selectedChat] = runCurrentChatFunction(db.characters[selectedChar].chats[selectedChat])
|
||||
currentChat = db.characters[selectedChar].chats[selectedChat]
|
||||
DBState.db.characters[selectedChar].chats[selectedChat] = runCurrentChatFunction(DBState.db.characters[selectedChar].chats[selectedChat])
|
||||
currentChat = DBState.db.characters[selectedChar].chats[selectedChat]
|
||||
|
||||
const triggerResult = await runTrigger(currentChar, 'output', {chat:currentChat})
|
||||
if(triggerResult && triggerResult.chat){
|
||||
db.characters[selectedChar].chats[selectedChat] = triggerResult.chat
|
||||
setDatabase(db)
|
||||
DBState.db.characters[selectedChar].chats[selectedChat] = triggerResult.chat
|
||||
}
|
||||
if(triggerResult && triggerResult.sendAIprompt){
|
||||
resendChat = true
|
||||
@@ -1285,11 +1293,11 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
|
||||
let needsAutoContinue = false
|
||||
const resultTokens = await tokenize(result) + (arg.usedContinueTokens || 0)
|
||||
if(db.autoContinueMinTokens > 0 && resultTokens < db.autoContinueMinTokens){
|
||||
if(DBState.db.autoContinueMinTokens > 0 && resultTokens < DBState.db.autoContinueMinTokens){
|
||||
needsAutoContinue = true
|
||||
}
|
||||
|
||||
if(db.autoContinueChat && (!isLastCharPunctuation(result))){
|
||||
if(DBState.db.autoContinueChat && (!isLastCharPunctuation(result))){
|
||||
//if result doesn't end with punctuation or special characters, auto continue
|
||||
needsAutoContinue = true
|
||||
}
|
||||
@@ -1358,7 +1366,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
tempEmotion.splice(0, 1)
|
||||
}
|
||||
|
||||
if(db.emotionProcesser === 'embedding'){
|
||||
if(DBState.db.emotionProcesser === 'embedding'){
|
||||
const hypaProcesser = new HypaProcesser('MiniLM')
|
||||
await hypaProcesser.addText(emotionList.map((v) => 'emotion:' + v))
|
||||
let searched = (await hypaProcesser.similaritySearchScored(result)).map((v) => {
|
||||
@@ -1437,7 +1445,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
const promptbody:OpenAIChat[] = [
|
||||
{
|
||||
role:'system',
|
||||
content: `${db.emotionPrompt2 || "From the list below, choose a word that best represents a character's outfit description, action, or emotion in their dialogue. Prioritize selecting words related to outfit first, then action, and lastly emotion. Print out the chosen word."}\n\n list: ${shuffleArray(emotionList).join(', ')} \noutput only one word.`
|
||||
content: `${DBState.db.emotionPrompt2 || "From the list below, choose a word that best represents a character's outfit description, action, or emotion in their dialogue. Prioritize selecting words related to outfit first, then action, and lastly emotion. Print out the chosen word."}\n\n list: ${shuffleArray(emotionList).join(', ')} \noutput only one word.`
|
||||
},
|
||||
{
|
||||
role: 'user',
|
||||
@@ -1457,9 +1465,8 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
formated: promptbody,
|
||||
bias: emobias,
|
||||
currentChar: currentChar,
|
||||
temperature: 0.4,
|
||||
maxTokens: 30,
|
||||
}, 'submodel', abortSignal)
|
||||
}, 'emotion', abortSignal)
|
||||
|
||||
if(rq.type === 'fail' || rq.type === 'streaming' || rq.type === 'multiline'){
|
||||
if(abortSignal.aborted){
|
||||
@@ -1520,7 +1527,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{
|
||||
alertError("Stable diffusion in group chat is not supported")
|
||||
}
|
||||
|
||||
const msgs = db.characters[selectedChar].chats[selectedChat].message
|
||||
const msgs = DBState.db.characters[selectedChar].chats[selectedChat].message
|
||||
let msgStr = ''
|
||||
for(let i = (msgs.length - 1);i>=0;i--){
|
||||
if(msgs[i].role === 'char'){
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getChatVar, getGlobalChatVar } from "../parser";
|
||||
import { getChatVar, getGlobalChatVar } from "../parser.svelte";
|
||||
|
||||
function toRPN(expression:string) {
|
||||
let outputQueue = '';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { writeInlayImage } from "./files/image";
|
||||
import type { character } from "../storage/database";
|
||||
import type { character } from "../storage/database.svelte";
|
||||
import { generateAIImage } from "./stableDiff";
|
||||
|
||||
const imggenRegex = [/<ImgGen="(.+?)">/gi, /{{ImgGen="(.+?)"}}/gi] as const
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
import { get } from "svelte/store";
|
||||
import {selectedCharID} from '../stores'
|
||||
import { DataBase, setDatabase, type Message, type loreBook } from "../storage/database";
|
||||
import {selectedCharID} from '../stores.svelte'
|
||||
import { type Message, type loreBook } from "../storage/database.svelte";
|
||||
import { DBState } from '../stores.svelte';
|
||||
import { tokenize } from "../tokenizer";
|
||||
import { checkNullish, selectSingleFile } from "../util";
|
||||
import { checkNullish, findCharacterbyId, selectSingleFile } from "../util";
|
||||
import { alertError, alertNormal } from "../alert";
|
||||
import { language } from "../../lang";
|
||||
import { downloadFile } from "../storage/globalApi";
|
||||
import { HypaProcesser } from "./memory/hypamemory";
|
||||
import { downloadFile } from "../globalApi.svelte";
|
||||
import { getModuleLorebooks } from "./modules";
|
||||
import { CCardLib } from "@risuai/ccardlib";
|
||||
|
||||
export function addLorebook(type:number) {
|
||||
let selectedID = get(selectedCharID)
|
||||
let db = get(DataBase)
|
||||
const selectedID = get(selectedCharID)
|
||||
if(type === 0){
|
||||
db.characters[selectedID].globalLore.push({
|
||||
DBState.db.characters[selectedID].globalLore.push({
|
||||
key: '',
|
||||
comment: `New Lore ${db.characters[selectedID].globalLore.length + 1}`,
|
||||
comment: `New Lore ${DBState.db.characters[selectedID].globalLore.length + 1}`,
|
||||
content: '',
|
||||
mode: 'normal',
|
||||
insertorder: 100,
|
||||
@@ -26,10 +25,10 @@ export function addLorebook(type:number) {
|
||||
})
|
||||
}
|
||||
else{
|
||||
const page = db.characters[selectedID].chatPage
|
||||
db.characters[selectedID].chats[page].localLore.push({
|
||||
const page = DBState.db.characters[selectedID].chatPage
|
||||
DBState.db.characters[selectedID].chats[page].localLore.push({
|
||||
key: '',
|
||||
comment: `New Lore ${db.characters[selectedID].chats[page].localLore.length + 1}`,
|
||||
comment: `New Lore ${DBState.db.characters[selectedID].chats[page].localLore.length + 1}`,
|
||||
content: '',
|
||||
mode: 'normal',
|
||||
insertorder: 100,
|
||||
@@ -38,245 +37,145 @@ export function addLorebook(type:number) {
|
||||
selective: false
|
||||
})
|
||||
}
|
||||
setDatabase(db)
|
||||
}
|
||||
|
||||
interface formatedLore{
|
||||
keys:string[]|'always'|{type:'regex',regex:string},
|
||||
secondKey:string[]|{type:'regex',regex:string}
|
||||
content: string
|
||||
order: number
|
||||
activatied: boolean
|
||||
}
|
||||
|
||||
const rmRegex = / |\n/g
|
||||
|
||||
export async function loadLoreBookPrompt(){
|
||||
|
||||
const selectedID = get(selectedCharID)
|
||||
const db = get(DataBase)
|
||||
const char = db.characters[selectedID]
|
||||
const page = char.chatPage
|
||||
const characterLore = char.globalLore ?? []
|
||||
const chatLore = char.chats[page].localLore ?? []
|
||||
const moduleLorebook = getModuleLorebooks()
|
||||
const fullLore = characterLore.concat(chatLore).concat(moduleLorebook)
|
||||
const currentChat = char.chats[page].message
|
||||
const loreDepth = char.loreSettings?.scanDepth ?? db.loreBookDepth
|
||||
const loreToken = char.loreSettings?.tokenBudget ?? db.loreBookToken
|
||||
const fullWordMatching = char.loreSettings?.fullWordMatching ?? false
|
||||
|
||||
let activatiedPrompt: string[] = []
|
||||
|
||||
let formatedLore:formatedLore[] = []
|
||||
|
||||
for (const lore of fullLore){
|
||||
if(lore){
|
||||
if(lore.key.length > 1 || lore.alwaysActive){
|
||||
if(!checkNullish(lore.activationPercent)){
|
||||
let activationPercent = lore.activationPercent
|
||||
if(isNaN(activationPercent) || !activationPercent || activationPercent < 0){
|
||||
activationPercent = 0
|
||||
}
|
||||
if(activationPercent < (Math.random() * 100)){
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if(lore.key?.startsWith('@@@')){
|
||||
lore.key = lore.key.replace('@@@','@@')
|
||||
}
|
||||
formatedLore.push({
|
||||
keys: lore.alwaysActive ? 'always' : (lore.key?.startsWith("@@regex ")) ? ({type:'regex',regex:lore.key.replace('@@regex ','')}) :
|
||||
(lore.key ?? '').replace(rmRegex, '').toLocaleLowerCase().split(',').filter((a) => {
|
||||
return a.length > 1
|
||||
}),
|
||||
secondKey: lore.selective ? ((lore.secondkey?.startsWith("@@regex ")) ? ({type:'regex',regex:lore.secondkey.replace('@@regex ','')}) :
|
||||
(lore.secondkey ?? '').replace(rmRegex, '').toLocaleLowerCase().split(',').filter((a) => {
|
||||
return a.length > 1
|
||||
})) : [],
|
||||
content: lore.content,
|
||||
order: lore.insertorder,
|
||||
activatied: false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
formatedLore.sort((a, b) => {
|
||||
return b.order - a.order
|
||||
})
|
||||
|
||||
const formatedChatMain = currentChat.slice(currentChat.length - loreDepth,currentChat.length).map((msg) => {
|
||||
return msg.data
|
||||
}).join('||').replace(rmRegex,'').toLocaleLowerCase()
|
||||
|
||||
let loreListUpdated = true
|
||||
|
||||
while(loreListUpdated){
|
||||
loreListUpdated = false
|
||||
const formatedChat = formatedChatMain + activatiedPrompt.join('').replace(rmRegex,'').toLocaleLowerCase()
|
||||
const formatedChatList = fullWordMatching ? formatedChat.split(' ') : formatedChat
|
||||
for(let i=0;i<formatedLore.length;i++){
|
||||
const lore = formatedLore[i]
|
||||
if(lore.activatied){
|
||||
continue
|
||||
}
|
||||
const totalTokens = await tokenize(activatiedPrompt.concat([lore.content]).join('\n\n'))
|
||||
if(totalTokens > loreToken){
|
||||
break
|
||||
}
|
||||
|
||||
if(lore.keys === 'always'){
|
||||
activatiedPrompt.push(lore.content)
|
||||
lore.activatied = true
|
||||
loreListUpdated = true
|
||||
continue
|
||||
}
|
||||
|
||||
let firstKeyActivation = false
|
||||
if(Array.isArray(lore.keys)){
|
||||
for(const key of lore.keys){
|
||||
if(key){
|
||||
if(formatedChatList.includes(key)){
|
||||
firstKeyActivation = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(formatedChat.match(new RegExp(lore.keys.regex,'g'))){
|
||||
firstKeyActivation = true
|
||||
}
|
||||
}
|
||||
|
||||
if(firstKeyActivation){
|
||||
if(Array.isArray(lore.secondKey)){
|
||||
if(lore.secondKey.length === 0){
|
||||
activatiedPrompt.push(lore.content)
|
||||
lore.activatied = true
|
||||
loreListUpdated = true
|
||||
continue
|
||||
}
|
||||
for(const key of lore.secondKey){
|
||||
if(formatedChatList.includes(key)){
|
||||
activatiedPrompt.push(lore.content)
|
||||
lore.activatied = true
|
||||
loreListUpdated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(formatedChat.match(new RegExp(lore.secondKey.regex,'g'))){
|
||||
firstKeyActivation = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!(char.loreSettings?.recursiveScanning)){
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let sactivated:string[] = []
|
||||
let decoratedArray:{
|
||||
depth:number,
|
||||
pos:string,
|
||||
prompt:string
|
||||
}[] = []
|
||||
activatiedPrompt = activatiedPrompt.filter((v) => {
|
||||
if(v.startsWith("@@@end")){
|
||||
sactivated.push(v.replace('@@@end','').trim())
|
||||
return false
|
||||
}
|
||||
if(v.startsWith('@@end')){
|
||||
sactivated.push(v.replace('@@end','').trim())
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return {
|
||||
act: activatiedPrompt.reverse().join('\n\n'),
|
||||
special_act: sactivated.reverse().join('\n\n'),
|
||||
decorated: decoratedArray
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function loadLoreBookV3Prompt(){
|
||||
const selectedID = get(selectedCharID)
|
||||
const db = get(DataBase)
|
||||
const char = db.characters[selectedID]
|
||||
const char = DBState.db.characters[selectedID]
|
||||
const page = char.chatPage
|
||||
const characterLore = char.globalLore ?? []
|
||||
const chatLore = char.chats[page].localLore ?? []
|
||||
const moduleLorebook = getModuleLorebooks()
|
||||
const fullLore = structuredClone(characterLore.concat(chatLore).concat(moduleLorebook))
|
||||
const fullLore = safeStructuredClone(characterLore.concat(chatLore).concat(moduleLorebook))
|
||||
const currentChat = char.chats[page].message
|
||||
const loreDepth = char.loreSettings?.scanDepth ?? db.loreBookDepth
|
||||
const loreToken = char.loreSettings?.tokenBudget ?? db.loreBookToken
|
||||
const fullWordMatching = char.loreSettings?.fullWordMatching ?? false
|
||||
const loreDepth = char.loreSettings?.scanDepth ?? DBState.db.loreBookDepth
|
||||
const loreToken = char.loreSettings?.tokenBudget ?? DBState.db.loreBookToken
|
||||
const fullWordMatchingSetting = char.loreSettings?.fullWordMatching ?? false
|
||||
const chatLength = currentChat.length + 1 //includes first message
|
||||
const recursiveScanning = char.loreSettings?.recursiveScanning ?? false
|
||||
let recursiveAdditionalPrompt = ''
|
||||
const recursiveScanning = char.loreSettings?.recursiveScanning ?? true
|
||||
let recursivePrompt:{
|
||||
prompt: string,
|
||||
source: string
|
||||
}[] = []
|
||||
let matchLog:{
|
||||
prompt: string,
|
||||
source: string
|
||||
activated: string
|
||||
}[] = []
|
||||
|
||||
const searchMatch = (messages:Message[],arg:{
|
||||
keys:string[],
|
||||
searchDepth:number,
|
||||
regex:boolean
|
||||
fullWordMatching:boolean
|
||||
recursiveAdditionalPrompt:string
|
||||
all?:boolean
|
||||
}) => {
|
||||
const sliced = messages.slice(messages.length - arg.searchDepth,messages.length)
|
||||
arg.keys = arg.keys.map(key => key.trim()).filter(key => key.length > 0)
|
||||
let mText = sliced.map((msg) => {
|
||||
return msg.data
|
||||
}).join('||')
|
||||
if(arg.recursiveAdditionalPrompt){
|
||||
mText += arg.recursiveAdditionalPrompt
|
||||
}
|
||||
if(arg.regex){
|
||||
for(const regexString of arg.keys){
|
||||
if(!regexString.startsWith('/')){
|
||||
return false
|
||||
let mList:{
|
||||
source:string
|
||||
prompt:string
|
||||
}[] = sliced.map((msg, i) => {
|
||||
if(msg.role === 'user'){
|
||||
return {
|
||||
source: `message ${i} by user`,
|
||||
prompt: `\x01{{${DBState.db.username}}}:` + msg.data + '\x01'
|
||||
}
|
||||
const regexFlag = regexString.split('/').pop()
|
||||
if(regexFlag){
|
||||
arg.keys[0] = regexString.replace('/'+regexFlag,'')
|
||||
try {
|
||||
const regex = new RegExp(arg.keys[0],regexFlag)
|
||||
return regex.test(mText)
|
||||
} catch (error) {
|
||||
}
|
||||
else{
|
||||
return {
|
||||
source: `message ${i} by char`,
|
||||
prompt: `\x01{{${msg.name ?? (msg.saying ? findCharacterbyId(msg.saying)?.name : null) ?? char.name}}}:` + msg.data + '\x01'
|
||||
}
|
||||
}
|
||||
}).concat(recursivePrompt.map((msg) => {
|
||||
return {
|
||||
source: 'lorebook ' + msg.source,
|
||||
prompt: msg.prompt
|
||||
}
|
||||
}))
|
||||
|
||||
if(arg.regex){
|
||||
for(const mText of mList){
|
||||
for(const regexString of arg.keys){
|
||||
if(!regexString.startsWith('/')){
|
||||
return false
|
||||
}
|
||||
const regexFlag = regexString.split('/').pop()
|
||||
if(regexFlag){
|
||||
arg.keys[0] = regexString.replace('/'+regexFlag,'')
|
||||
try {
|
||||
const regex = new RegExp(arg.keys[0],regexFlag)
|
||||
const d = regex.test(mText.prompt)
|
||||
if(d){
|
||||
matchLog.push({
|
||||
prompt: mText.prompt,
|
||||
source: mText.source,
|
||||
activated: regexString
|
||||
})
|
||||
return true
|
||||
}
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
mText = mText.toLocaleLowerCase()
|
||||
mText = mText.replace(/\{\{\/\/(.+?)\}\}/g,'').replace(/\{\{comment:(.+?)\}\}/g,'')
|
||||
mList = mList.map((m) => {
|
||||
return {
|
||||
source: m.source,
|
||||
prompt: m.prompt.toLocaleLowerCase().replace(/\{\{\/\/(.+?)\}\}/g,'').replace(/\{\{comment:(.+?)\}\}/g,'')
|
||||
}
|
||||
})
|
||||
|
||||
if(arg.fullWordMatching){
|
||||
const splited = mText.split(' ')
|
||||
for(const key of arg.keys){
|
||||
if(splited.includes(key.toLocaleLowerCase())){
|
||||
return true
|
||||
let allMode = arg.all ?? false
|
||||
let allModeMatched = true
|
||||
|
||||
for(const m of mList){
|
||||
let mText = m.prompt
|
||||
if(arg.fullWordMatching){
|
||||
const splited = mText.split(' ')
|
||||
for(const key of arg.keys){
|
||||
if(splited.includes(key.toLocaleLowerCase())){
|
||||
matchLog.push({
|
||||
prompt: m.prompt,
|
||||
source: m.source,
|
||||
activated: key
|
||||
})
|
||||
if(!allMode){
|
||||
return true
|
||||
}
|
||||
}
|
||||
else if(allMode){
|
||||
allModeMatched = false
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
mText = mText.replace(/ /g,'')
|
||||
for(const key of arg.keys){
|
||||
const realKey = key.toLocaleLowerCase().replace(/ /g,'')
|
||||
if(mText.includes(realKey)){
|
||||
matchLog.push({
|
||||
prompt: m.prompt,
|
||||
source: m.source,
|
||||
activated: key
|
||||
})
|
||||
if(!allMode){
|
||||
return true
|
||||
}
|
||||
}
|
||||
else if(allMode){
|
||||
allModeMatched = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
mText = mText.replace(/ /g,'')
|
||||
for(const key of arg.keys){
|
||||
const realKey = key.toLocaleLowerCase().replace(/ /g,'')
|
||||
if(mText.includes(realKey)){
|
||||
return true
|
||||
}
|
||||
}
|
||||
if(allMode && allModeMatched){
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -291,6 +190,7 @@ export async function loadLoreBookV3Prompt(){
|
||||
order:number
|
||||
tokens:number
|
||||
priority:number
|
||||
source:string
|
||||
}[] = []
|
||||
let activatedIndexes:number[] = []
|
||||
let disabledUIPrompts:string[] = []
|
||||
@@ -314,8 +214,10 @@ export async function loadLoreBookV3Prompt(){
|
||||
let role:'system'|'user'|'assistant' = 'system'
|
||||
let searchQueries:{
|
||||
keys:string[],
|
||||
negative:boolean
|
||||
negative:boolean,
|
||||
all?:boolean
|
||||
}[] = []
|
||||
let fullWordMatching = fullWordMatchingSetting
|
||||
const content = CCardLib.decorator.parse(fullLore[i].content, (name, arg) => {
|
||||
switch(name){
|
||||
case 'end':{
|
||||
@@ -412,6 +314,22 @@ export async function loadLoreBookV3Prompt(){
|
||||
})
|
||||
return
|
||||
}
|
||||
case 'exclude_keys_all':{
|
||||
searchQueries.push({
|
||||
keys: arg,
|
||||
negative: true,
|
||||
all: true
|
||||
})
|
||||
return
|
||||
}
|
||||
case 'match_full_word':{
|
||||
fullWordMatching = true
|
||||
return
|
||||
}
|
||||
case 'match_partial_word':{
|
||||
fullWordMatching = false
|
||||
return
|
||||
}
|
||||
case 'is_user_icon':{
|
||||
//TODO
|
||||
return false
|
||||
@@ -455,6 +373,13 @@ export async function loadLoreBookV3Prompt(){
|
||||
keys: fullLore[i].key.split(','),
|
||||
negative: false
|
||||
})
|
||||
|
||||
if(fullLore[i].secondkey && fullLore[i].selective){
|
||||
searchQueries.push({
|
||||
keys: fullLore[i].secondkey.split(','),
|
||||
negative: false
|
||||
})
|
||||
}
|
||||
|
||||
for(const query of searchQueries){
|
||||
const result = searchMatch(currentChat, {
|
||||
@@ -462,7 +387,7 @@ export async function loadLoreBookV3Prompt(){
|
||||
searchDepth: scanDepth,
|
||||
regex: fullLore[i].useRegex,
|
||||
fullWordMatching: fullWordMatching,
|
||||
recursiveAdditionalPrompt: recursiveAdditionalPrompt
|
||||
all: query.all
|
||||
})
|
||||
if(query.negative){
|
||||
if(result){
|
||||
@@ -494,12 +419,16 @@ export async function loadLoreBookV3Prompt(){
|
||||
role: role,
|
||||
order: order,
|
||||
tokens: await tokenize(content),
|
||||
priority: priority
|
||||
priority: priority,
|
||||
source: fullLore[i].comment || `lorebook ${i}`
|
||||
})
|
||||
activatedIndexes.push(i)
|
||||
if(recursiveScanning){
|
||||
matching = true
|
||||
recursiveAdditionalPrompt += content + '\n\n'
|
||||
recursivePrompt.push({
|
||||
prompt: content,
|
||||
source: fullLore[i].comment || `lorebook ${i}`
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -524,18 +453,18 @@ export async function loadLoreBookV3Prompt(){
|
||||
})
|
||||
|
||||
return {
|
||||
actives: activesResorted.reverse()
|
||||
actives: activesResorted.reverse(),
|
||||
matchLog: matchLog,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export async function importLoreBook(mode:'global'|'local'|'sglobal'){
|
||||
const selectedID = get(selectedCharID)
|
||||
let db = get(DataBase)
|
||||
const page = mode === 'sglobal' ? -1 : db.characters[selectedID].chatPage
|
||||
const page = mode === 'sglobal' ? -1 : DBState.db.characters[selectedID].chatPage
|
||||
let lore =
|
||||
mode === 'global' ? db.characters[selectedID].globalLore :
|
||||
db.characters[selectedID].chats[page].localLore
|
||||
mode === 'global' ? DBState.db.characters[selectedID].globalLore :
|
||||
DBState.db.characters[selectedID].chats[page].localLore
|
||||
const lorebook = (await selectSingleFile(['json', 'lorebook'])).data
|
||||
if(!lorebook){
|
||||
return
|
||||
@@ -556,12 +485,11 @@ export async function importLoreBook(mode:'global'|'local'|'sglobal'){
|
||||
lore.push(...convertExternalLorebook(entries))
|
||||
}
|
||||
if(mode === 'global'){
|
||||
db.characters[selectedID].globalLore = lore
|
||||
DBState.db.characters[selectedID].globalLore = lore
|
||||
}
|
||||
else{
|
||||
db.characters[selectedID].chats[page].localLore = lore
|
||||
DBState.db.characters[selectedID].chats[page].localLore = lore
|
||||
}
|
||||
setDatabase(db)
|
||||
} catch (error) {
|
||||
alertError(`${error}`)
|
||||
}
|
||||
@@ -613,11 +541,10 @@ export function convertExternalLorebook(entries:{[key:string]:CCLorebook}){
|
||||
export async function exportLoreBook(mode:'global'|'local'|'sglobal'){
|
||||
try {
|
||||
const selectedID = get(selectedCharID)
|
||||
const db = get(DataBase)
|
||||
const page = mode === 'sglobal' ? -1 : db.characters[selectedID].chatPage
|
||||
const page = mode === 'sglobal' ? -1 : DBState.db.characters[selectedID].chatPage
|
||||
const lore =
|
||||
mode === 'global' ? db.characters[selectedID].globalLore :
|
||||
db.characters[selectedID].chats[page].localLore
|
||||
mode === 'global' ? DBState.db.characters[selectedID].globalLore :
|
||||
DBState.db.characters[selectedID].chats[page].localLore
|
||||
const stringl = Buffer.from(JSON.stringify({
|
||||
type: 'risu',
|
||||
ver: 1,
|
||||
@@ -1,13 +1,13 @@
|
||||
import { getChatVar, hasher, risuChatParser, setChatVar, type simpleCharacterArgument } from "../parser";
|
||||
import { getChatVar, hasher, setChatVar, type simpleCharacterArgument } from "../parser.svelte";
|
||||
import { LuaEngine, LuaFactory } from "wasmoon";
|
||||
import { DataBase, setDatabase, type Chat, type character, type groupChat } from "../storage/database";
|
||||
import { getCurrentCharacter, getCurrentChat, getDatabase, setCurrentChat, setDatabase, type Chat, type character, type groupChat } from "../storage/database.svelte";
|
||||
import { get } from "svelte/store";
|
||||
import { CurrentCharacter, CurrentChat, ReloadGUIPointer, selectedCharID } from "../stores";
|
||||
import { ReloadGUIPointer, selectedCharID } from "../stores.svelte";
|
||||
import { alertError, alertInput, alertNormal } from "../alert";
|
||||
import { HypaProcesser } from "./memory/hypamemory";
|
||||
import { generateAIImage } from "./stableDiff";
|
||||
import { writeInlayImage } from "./files/image";
|
||||
import type { OpenAIChat } from ".";
|
||||
import type { OpenAIChat } from "./index.svelte";
|
||||
import { requestChatData } from "./request";
|
||||
import { v4 } from "uuid";
|
||||
import { getModuleTriggers } from "./modules";
|
||||
@@ -35,12 +35,12 @@ export async function runLua(code:string, arg:{
|
||||
mode?: string,
|
||||
data?: any
|
||||
}){
|
||||
const char = arg.char ?? get(CurrentCharacter)
|
||||
const char = arg.char ?? getCurrentCharacter()
|
||||
const setVar = arg.setVar ?? setChatVar
|
||||
const getVar = arg.getVar ?? getChatVar
|
||||
const mode = arg.mode ?? 'manual'
|
||||
const data = arg.data ?? {}
|
||||
let chat = arg.chat ?? get(CurrentChat)
|
||||
let chat = arg.chat ?? getCurrentChat()
|
||||
let stopSending = false
|
||||
let lowLevelAccess = arg.lowLevelAccess ?? false
|
||||
|
||||
@@ -104,66 +104,75 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
const message = chat.message?.at(index)
|
||||
if(message){
|
||||
message.data = value
|
||||
}
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
luaEngine.global.set('setChatRole', (id:string, index:number, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
const message = chat.message?.at(index)
|
||||
if(message){
|
||||
message.role = value === 'user' ? 'user' : 'char'
|
||||
}
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
luaEngine.global.set('cutChat', (id:string, start:number, end:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
chat.message = chat.message.slice(start,end)
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
luaEngine.global.set('removeChat', (id:string, index:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
chat.message.splice(index, 1)
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
luaEngine.global.set('addChat', (id:string, role:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
|
||||
chat.message.push({role: roleData, data: value})
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
luaEngine.global.set('insertChat', (id:string, index:number, role:string, value:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
let roleData:'user'|'char' = role === 'user' ? 'user' : 'char'
|
||||
chat.message.splice(index, 0, {role: roleData, data: value})
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
luaEngine.global.set('removeChat', (id:string, index:number) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
chat.message.splice(index, 1)
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
luaEngine.global.set('getChatLength', (id:string) => {
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
return chat.message.length
|
||||
})
|
||||
luaEngine.global.set('getFullChatMain', (id:string) => {
|
||||
chat = getCurrentChat()
|
||||
const data = JSON.stringify(chat.message.map((v) => {
|
||||
return {
|
||||
role: v.role,
|
||||
@@ -178,13 +187,14 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
chat = getCurrentChat()
|
||||
chat.message = realValue.map((v) => {
|
||||
return {
|
||||
role: v.role,
|
||||
data: v.data
|
||||
}
|
||||
})
|
||||
CurrentChat.set(chat)
|
||||
setCurrentChat(chat)
|
||||
})
|
||||
|
||||
luaEngine.global.set('logMain', (value:string) => {
|
||||
@@ -322,7 +332,7 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.name
|
||||
@@ -332,7 +342,7 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof name !== 'string'){
|
||||
throw('Invalid data type')
|
||||
@@ -345,7 +355,7 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char =db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
@@ -363,7 +373,7 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
if(typeof data !== 'string'){
|
||||
@@ -379,7 +389,7 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.firstMessage
|
||||
@@ -389,7 +399,7 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const char = db.characters[selectedChar]
|
||||
return char.backgroundHTML
|
||||
@@ -399,7 +409,7 @@ export async function runLua(code:string, arg:{
|
||||
if(!LuaSafeIds.has(id)){
|
||||
return
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
if(typeof data !== 'string'){
|
||||
return false
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { alertError } from "src/ts/alert";
|
||||
import type { OpenAIChat } from "..";
|
||||
import type { OpenAIChat } from "../index.svelte";
|
||||
import { HypaProcesser } from "./hypamemory";
|
||||
import { language } from "src/lang";
|
||||
import type { ChatTokenizer } from "src/ts/tokenizer";
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase } from "src/ts/storage/database";
|
||||
import { getDatabase } from "src/ts/storage/database.svelte";
|
||||
|
||||
const maxRecentChatQuery = 4;
|
||||
export async function hanuraiMemory(chats:OpenAIChat[],arg:{
|
||||
@@ -12,7 +11,7 @@ export async function hanuraiMemory(chats:OpenAIChat[],arg:{
|
||||
maxContextTokens:number,
|
||||
tokenizer:ChatTokenizer
|
||||
}){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const tokenizer = arg.tokenizer
|
||||
const processer = new HypaProcesser('MiniLM')
|
||||
let addTexts:string[] = []
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import localforage from "localforage";
|
||||
import { globalFetch } from "src/ts/storage/globalApi";
|
||||
import { globalFetch } from "src/ts/globalApi.svelte";
|
||||
import { runEmbedding } from "../transformers";
|
||||
import { alertError } from "src/ts/alert";
|
||||
import { appendLastPath } from "src/ts/util";
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { DataBase, type Chat, type character, type groupChat } from "src/ts/storage/database";
|
||||
import type { OpenAIChat } from "..";
|
||||
import { getDatabase, type Chat, type character, type groupChat } from "src/ts/storage/database.svelte";
|
||||
import type { OpenAIChat } from "../index.svelte";
|
||||
import type { ChatTokenizer } from "src/ts/tokenizer";
|
||||
import { get } from "svelte/store";
|
||||
import { requestChatData } from "../request";
|
||||
import { HypaProcesser } from "./hypamemory";
|
||||
import { globalFetch } from "src/ts/storage/globalApi";
|
||||
import { globalFetch } from "src/ts/globalApi.svelte";
|
||||
import { runSummarizer } from "../transformers";
|
||||
import { last, remove } from "lodash";
|
||||
import { parseChatML } from "src/ts/parser.svelte";
|
||||
|
||||
export interface HypaV2Data {
|
||||
chunks: {
|
||||
@@ -20,7 +19,7 @@ export interface HypaV2Data {
|
||||
}
|
||||
|
||||
async function summary(stringlizedChat: string): Promise<{ success: boolean; data: string }> {
|
||||
const db = get(DataBase);
|
||||
const db = getDatabase();
|
||||
console.log("Summarizing");
|
||||
|
||||
if (db.supaModelType === 'distilbart') {
|
||||
@@ -85,7 +84,10 @@ async function summary(stringlizedChat: string): Promise<{ success: boolean; dat
|
||||
};
|
||||
}
|
||||
} else {
|
||||
const promptbody: OpenAIChat[] = [
|
||||
|
||||
let parsedPrompt = parseChatML(supaPrompt.replaceAll('{{slot}}', stringlizedChat))
|
||||
|
||||
const promptbody: OpenAIChat[] = parsedPrompt ?? [
|
||||
{
|
||||
role: "user",
|
||||
content: stringlizedChat
|
||||
@@ -101,7 +103,7 @@ async function summary(stringlizedChat: string): Promise<{ success: boolean; dat
|
||||
bias: {},
|
||||
useStreaming: false,
|
||||
noMultiGen: true
|
||||
}, 'submodel');
|
||||
}, 'memory');
|
||||
if (da.type === 'fail' || da.type === 'streaming' || da.type === 'multiline') {
|
||||
return {
|
||||
success: false,
|
||||
@@ -123,7 +125,7 @@ export async function hypaMemoryV2(
|
||||
arg: { asHyper?: boolean, summaryModel?: string, summaryPrompt?: string, hypaModel?: string } = {}
|
||||
): Promise<{ currentTokens: number; chats: OpenAIChat[]; error?: string; memory?: HypaV2Data; }> {
|
||||
|
||||
const db = get(DataBase);
|
||||
const db = getDatabase();
|
||||
const data: HypaV2Data = room.hypaV2Data ?? { chunks: [], mainChunks: [] };
|
||||
|
||||
let allocatedTokens = db.hypaAllocatedTokens;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { get } from "svelte/store";
|
||||
import type { OpenAIChat } from "..";
|
||||
import { DataBase, type Chat, type character, type groupChat } from "../../storage/database";
|
||||
import type { OpenAIChat } from "../index.svelte";
|
||||
import { getDatabase, type Chat, type character, type groupChat } from "../../storage/database.svelte";
|
||||
import { tokenize, type ChatTokenizer } from "../../tokenizer";
|
||||
import { requestChatData } from "../request";
|
||||
import { HypaProcesser } from "./hypamemory";
|
||||
import { stringlizeChat } from "../stringlize";
|
||||
import { globalFetch } from "src/ts/storage/globalApi";
|
||||
import { globalFetch } from "src/ts/globalApi.svelte";
|
||||
import { runSummarizer } from "../transformers";
|
||||
import { getUserName } from "src/ts/util";
|
||||
import { parseChatML } from "src/ts/parser.svelte";
|
||||
|
||||
export async function supaMemory(
|
||||
chats:OpenAIChat[],
|
||||
@@ -18,7 +18,7 @@ export async function supaMemory(
|
||||
tokenizer:ChatTokenizer,
|
||||
arg:{asHyper?:boolean} = {}
|
||||
): Promise<{ currentTokens: number; chats: OpenAIChat[]; error?:string; memory?:string;lastId?:string}>{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
|
||||
currentTokens += 10
|
||||
|
||||
@@ -74,7 +74,7 @@ export async function supaMemory(
|
||||
for(let j=0;j<HypaData.length;j++){
|
||||
let i =0;
|
||||
let countTokens = currentTokens
|
||||
let countChats = structuredClone(chats)
|
||||
let countChats = safeStructuredClone(chats)
|
||||
while(true){
|
||||
if(countChats.length === 0){
|
||||
break
|
||||
@@ -253,7 +253,8 @@ export async function supaMemory(
|
||||
}
|
||||
}
|
||||
else {
|
||||
const promptbody:OpenAIChat[] = [
|
||||
let parsedPrompt = parseChatML(supaPrompt.replaceAll('{{slot}}', stringlizedChat))
|
||||
const promptbody:OpenAIChat[] = parsedPrompt ?? [
|
||||
{
|
||||
role: "user",
|
||||
content: stringlizedChat
|
||||
@@ -268,7 +269,7 @@ export async function supaMemory(
|
||||
bias: {},
|
||||
useStreaming: false,
|
||||
noMultiGen: true
|
||||
}, 'submodel')
|
||||
}, 'memory')
|
||||
if(da.type === 'fail' || da.type === 'streaming' || da.type === 'multiline'){
|
||||
return {
|
||||
currentTokens: currentTokens,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { globalFetch } from "src/ts/storage/globalApi";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { globalFetch } from "src/ts/globalApi.svelte";
|
||||
import { sleep } from "src/ts/util";
|
||||
import * as path from "@tauri-apps/api/path";
|
||||
import { exists, readTextFile } from "@tauri-apps/api/fs";
|
||||
import { exists, readTextFile } from "@tauri-apps/plugin-fs";
|
||||
import { alertClear, alertError, alertMd, alertWait } from "src/ts/alert";
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase } from "src/ts/storage/database";
|
||||
import { resolveResource } from '@tauri-apps/api/path'
|
||||
import { getDatabase } from "src/ts/storage/database.svelte";
|
||||
let serverRunning = false;
|
||||
|
||||
export function checkLocalModel():Promise<string>{
|
||||
@@ -131,7 +129,7 @@ export async function loadExllamaFull(){
|
||||
|
||||
|
||||
async function runLocalModelOld(prompt:string){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
|
||||
if(!serverRunning){
|
||||
await loadExllamaFull()
|
||||
@@ -274,7 +272,7 @@ export async function runGGUFModel(arg:{
|
||||
|
||||
export async function tokenizeGGUFModel(prompt:string):Promise<number[]> {
|
||||
const key = await getLocalKey()
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const modelPath = db.aiModel.replace('local_', '')
|
||||
const b = await fetch("http://localhost:10026/llamacpp/tokenize", {
|
||||
method: "POST",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { DataBase } from "src/ts/storage/database";
|
||||
import { get } from "svelte/store";
|
||||
import { getDatabase } from "src/ts/storage/database.svelte";
|
||||
|
||||
export function getGenerationModelString(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
switch (db.aiModel){
|
||||
case 'reverse_proxy':
|
||||
return 'reverse_proxy-' + (db.reverseProxyOobaMode ? 'ooba' : db.proxyRequestModel)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { DataBase, setDatabase } from "src/ts/storage/database"
|
||||
import type { OpenAIChat } from ".."
|
||||
import { get } from "svelte/store"
|
||||
import { globalFetch } from "src/ts/storage/globalApi"
|
||||
import { getDatabase, setDatabase } from "src/ts/storage/database.svelte"
|
||||
import type { OpenAIChat } from "../index.svelte"
|
||||
import { globalFetch } from "src/ts/globalApi.svelte"
|
||||
import { alertError, alertInput, alertNormal, alertWait } from "src/ts/alert"
|
||||
import { getUserName, sleep } from "src/ts/util"
|
||||
|
||||
export function stringlizeNAIChat(formated:OpenAIChat[], char:string, continued: boolean){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let seperator = db.NAIsettings.seperator.replaceAll("\\n","\n") || '\n'
|
||||
let starter = db.NAIsettings.starter.replaceAll("\\n","\n") || '⁂'
|
||||
let resultString:string[] = []
|
||||
@@ -109,7 +108,7 @@ export const novelLogin = async () => {
|
||||
|
||||
const data = r.data?.accessToken
|
||||
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
db.novelai.token = data
|
||||
|
||||
alertNormal('Logged in to NovelAI')
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { language } from "src/lang"
|
||||
import { alertConfirm, alertError, alertModuleSelect, alertNormal, alertStore } from "../alert"
|
||||
import { DataBase, setDatabase, type customscript, type loreBook, type triggerscript } from "../storage/database"
|
||||
import { AppendableBuffer, downloadFile, isNodeServer, isTauri, readImage, saveAsset } from "../storage/globalApi"
|
||||
import { get } from "svelte/store"
|
||||
import { CurrentCharacter, CurrentChat } from "../stores"
|
||||
import { getCurrentCharacter, getCurrentChat, getDatabase, setCurrentCharacter, setDatabase, type customscript, type loreBook, type triggerscript } from "../storage/database.svelte"
|
||||
import { AppendableBuffer, downloadFile, isNodeServer, isTauri, readImage, saveAsset } from "../globalApi.svelte"
|
||||
import { selectSingleFile, sleep } from "../util"
|
||||
import { v4 } from "uuid"
|
||||
import { convertExternalLorebook } from "./lorebook"
|
||||
import { encode } from "msgpackr"
|
||||
import { convertExternalLorebook } from "./lorebook.svelte"
|
||||
import { decodeRPack, encodeRPack } from "../rpack/rpack_bg"
|
||||
import { convertImage } from "../parser"
|
||||
import { convertImage } from "../parser.svelte"
|
||||
import { Capacitor } from "@capacitor/core"
|
||||
import { HideIconStore, moduleBackgroundEmbedding, ReloadGUIPointer } from "../stores.svelte"
|
||||
import {get} from "svelte/store"
|
||||
|
||||
export interface RisuModule{
|
||||
name: string
|
||||
@@ -47,7 +46,7 @@ export async function exportModule(module:RisuModule, arg:{
|
||||
}
|
||||
|
||||
const assets = module.assets ?? []
|
||||
module = structuredClone(module)
|
||||
module = safeStructuredClone(module)
|
||||
module.assets ??= []
|
||||
module.assets = module.assets.map((asset) => {
|
||||
return [asset[0], '', asset[2]] as [string,string,string]
|
||||
@@ -173,7 +172,7 @@ export async function importModule(){
|
||||
return
|
||||
}
|
||||
let fileData = f.data
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(f.name.endsWith('.risum')){
|
||||
try {
|
||||
const buf = Buffer.from(fileData)
|
||||
@@ -250,7 +249,7 @@ export async function importModule(){
|
||||
}
|
||||
|
||||
function getModuleById(id:string){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
for(let i=0;i<db.modules.length;i++){
|
||||
if(db.modules[i].id === id){
|
||||
return db.modules[i]
|
||||
@@ -261,7 +260,7 @@ function getModuleById(id:string){
|
||||
|
||||
function getModuleByIds(ids:string[]){
|
||||
let modules:RisuModule[] = []
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
for(let i=0;i<ids.length;i++){
|
||||
const module = db.modules.find((m) => m.id === ids[i] || (m.namespace === ids[i] && m.namespace))
|
||||
if(module){
|
||||
@@ -274,8 +273,8 @@ function getModuleByIds(ids:string[]){
|
||||
let lastModules = ''
|
||||
let lastModuleData:RisuModule[] = []
|
||||
export function getModules(){
|
||||
const currentChat = get(CurrentChat)
|
||||
const db = get(DataBase)
|
||||
const currentChat = getCurrentChat()
|
||||
const db = getDatabase()
|
||||
let ids = db.enabledModules ?? []
|
||||
if (currentChat){
|
||||
ids = ids.concat(currentChat.modules ?? [])
|
||||
@@ -363,12 +362,12 @@ export async function applyModule() {
|
||||
return
|
||||
}
|
||||
|
||||
const module = structuredClone(getModuleById(sel))
|
||||
const module = safeStructuredClone(getModuleById(sel))
|
||||
if (!module) {
|
||||
return
|
||||
}
|
||||
|
||||
const currentChar = get(CurrentCharacter)
|
||||
const currentChar = getCurrentCharacter()
|
||||
if (!currentChar) {
|
||||
return
|
||||
}
|
||||
@@ -392,7 +391,42 @@ export async function applyModule() {
|
||||
}
|
||||
}
|
||||
|
||||
CurrentCharacter.set(currentChar)
|
||||
setCurrentCharacter(currentChar)
|
||||
|
||||
alertNormal(language.successApplyModule)
|
||||
}
|
||||
|
||||
let lastModuleIds:string = ''
|
||||
|
||||
export function moduleUpdate(){
|
||||
|
||||
|
||||
const m = getModules()
|
||||
|
||||
const ids = m.map((m) => m.id).join('-')
|
||||
|
||||
let moduleHideIcon = false
|
||||
let backgroundEmbedding = ''
|
||||
m.forEach((module) => {
|
||||
if(!module){
|
||||
return
|
||||
}
|
||||
|
||||
if(module.hideIcon){
|
||||
moduleHideIcon = true
|
||||
}
|
||||
if(module.backgroundEmbedding){
|
||||
backgroundEmbedding += '\n' + module.backgroundEmbedding + '\n'
|
||||
}
|
||||
})
|
||||
|
||||
if(backgroundEmbedding){
|
||||
moduleBackgroundEmbedding.set(backgroundEmbedding)
|
||||
}
|
||||
HideIconStore.set(getCurrentCharacter()?.hideChatIcon || moduleHideIcon)
|
||||
|
||||
if(lastModuleIds !== ids){
|
||||
ReloadGUIPointer.set(get(ReloadGUIPointer) + 1)
|
||||
lastModuleIds = ids
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AppendableBuffer, isNodeServer, isTauri, saveAsset, type LocalWriter, type VirtualWriter } from "../storage/globalApi";
|
||||
import { AppendableBuffer, isNodeServer, isTauri, saveAsset, type LocalWriter, type VirtualWriter } from "../globalApi.svelte";
|
||||
import * as fflate from "fflate";
|
||||
import { sleep } from "../util";
|
||||
import { alertStore } from "../alert";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { get } from "svelte/store";
|
||||
import { tokenizeAccurate } from "../tokenizer";
|
||||
import { DataBase, presetTemplate, setDatabase, type Database } from "../storage/database";
|
||||
import { getDatabase, presetTemplate, setDatabase, type Database } from "../storage/database.svelte";
|
||||
import { alertError, alertNormal } from "../alert";
|
||||
import type { OobaChatCompletionRequestParams } from "../model/ooba";
|
||||
|
||||
@@ -256,7 +256,7 @@ export const OobaParams = [
|
||||
]
|
||||
|
||||
export function promptConvertion(files:{ name: string, content: string, type:string }[]){
|
||||
let preset = structuredClone(presetTemplate)
|
||||
let preset = safeStructuredClone(presetTemplate)
|
||||
let instData = {
|
||||
"system_prompt": "",
|
||||
"input_sequence": "",
|
||||
@@ -383,7 +383,7 @@ export function promptConvertion(files:{ name: string, content: string, type:str
|
||||
if(type === 'STCHAT'){
|
||||
preset.aiModel = 'openrouter'
|
||||
preset.subModel = 'openrouter'
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
db.botPresets.push(preset)
|
||||
setDatabase(db)
|
||||
|
||||
@@ -461,7 +461,7 @@ export function promptConvertion(files:{ name: string, content: string, type:str
|
||||
preset.name ||= 'Converted from JSON'
|
||||
|
||||
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
db.botPresets.push(preset)
|
||||
setDatabase(db)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
||||
import { get } from "svelte/store";
|
||||
import { CharEmotion, selectedCharID } from "../stores";
|
||||
import { DataBase, setDatabase, type character, type customscript, type groupChat, type Database } from "../storage/database";
|
||||
import { downloadFile } from "../storage/globalApi";
|
||||
import { CharEmotion, selectedCharID } from "../stores.svelte";
|
||||
import { type character, type customscript, type groupChat, type Database, getDatabase } from "../storage/database.svelte";
|
||||
import { downloadFile } from "../globalApi.svelte";
|
||||
import { alertError, alertNormal } from "../alert";
|
||||
import { language } from "src/lang";
|
||||
import { selectSingleFile } from "../util";
|
||||
import { assetRegex, type CbsConditions, risuChatParser as risuChatParserOrg, type simpleCharacterArgument } from "../parser";
|
||||
import { assetRegex, type CbsConditions, risuChatParser as risuChatParserOrg, type simpleCharacterArgument } from "../parser.svelte";
|
||||
import { runCharacterJS } from "../plugins/embedscript";
|
||||
import { getModuleAssets, getModuleRegexScripts } from "./modules";
|
||||
import { HypaProcesser } from "./memory/hypamemory";
|
||||
@@ -27,7 +27,7 @@ export async function processScript(char:character|groupChat, data:string, mode:
|
||||
}
|
||||
|
||||
export function exportRegex(s?:customscript[]){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const script = s ?? db.globalscript
|
||||
const data = Buffer.from(JSON.stringify({
|
||||
type: 'regex',
|
||||
@@ -43,7 +43,7 @@ export async function importRegex(o?:customscript[]):Promise<customscript[]>{
|
||||
if(!filedata){
|
||||
return o
|
||||
}
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
try {
|
||||
const imported= JSON.parse(Buffer.from(filedata).toString('utf-8'))
|
||||
if(imported.type === 'regex' && imported.data){
|
||||
@@ -65,9 +65,42 @@ export async function importRegex(o?:customscript[]):Promise<customscript[]>{
|
||||
}
|
||||
|
||||
let bestMatchCache = new Map<string, string>()
|
||||
let processScriptCache = new Map<string, string>()
|
||||
|
||||
function cacheScript(scripts:customscript[], data:string, result:string, mode:ScriptMode){
|
||||
let hash = data + '|||' + mode + '|||'
|
||||
for(const script of scripts){
|
||||
hash += `${script.in}|||${script.out}|||${script.flag}|||${script.ableFlag}|||${script.type}`
|
||||
}
|
||||
|
||||
processScriptCache.set(hash, result)
|
||||
|
||||
if(processScriptCache.size > 500){
|
||||
processScriptCache.delete(processScriptCache.keys().next().value)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getScriptCache(scripts:customscript[], data:string, mode:ScriptMode){
|
||||
let hash = data + '|||' + mode + '|||'
|
||||
for(const script of scripts){
|
||||
hash += `${script.in}|||${script.out}|||${script.flag}|||${script.ableFlag}|||${script.type}`
|
||||
}
|
||||
|
||||
return processScriptCache.get(hash)
|
||||
}
|
||||
|
||||
export function resetScriptCache(){
|
||||
processScriptCache = new Map()
|
||||
}
|
||||
|
||||
export async function processScriptFull(char:character|groupChat|simpleCharacterArgument, data:string, mode:ScriptMode, chatID = -1, cbsConditions:CbsConditions = {}){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const originalData = data
|
||||
const cached = getScriptCache((db.globalscript ?? []).concat(char.customscript), originalData, mode)
|
||||
if(cached){
|
||||
return {data: cached, emoChanged: false}
|
||||
}
|
||||
let emoChanged = false
|
||||
const scripts = (db.globalscript ?? []).concat(char.customscript).concat(getModuleRegexScripts())
|
||||
data = await runCharacterJS({
|
||||
@@ -77,6 +110,7 @@ export async function processScriptFull(char:character|groupChat|simpleCharacter
|
||||
})
|
||||
data = await runLuaEditTrigger(char, mode, data)
|
||||
if(scripts.length === 0){
|
||||
cacheScript(scripts, originalData, data, mode)
|
||||
return {data, emoChanged}
|
||||
}
|
||||
function executeScript(pscript:pScript){
|
||||
@@ -231,7 +265,7 @@ export async function processScriptFull(char:character|groupChat|simpleCharacter
|
||||
for (const script of scripts){
|
||||
if(script.ableFlag && script.flag?.includes('<')){
|
||||
const rregex = /<(.+?)>/g
|
||||
const scriptData = structuredClone(script)
|
||||
const scriptData = safeStructuredClone(script)
|
||||
let order = 0
|
||||
const actions:string[] = []
|
||||
scriptData.flag = scriptData.flag?.replace(rregex, (v:string, p1:string) => {
|
||||
@@ -311,6 +345,8 @@ export async function processScriptFull(char:character|groupChat|simpleCharacter
|
||||
}
|
||||
}
|
||||
|
||||
cacheScript(scripts, originalData, data, mode)
|
||||
|
||||
return {data, emoChanged}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { get } from "svelte/store"
|
||||
import { DataBase, type character } from "../storage/database"
|
||||
import { getDatabase, type character } from "../storage/database.svelte"
|
||||
import { requestChatData } from "./request"
|
||||
import { alertError } from "../alert"
|
||||
import { globalFetch, readImage } from "../storage/globalApi"
|
||||
import { CharEmotion } from "../stores"
|
||||
import type { OpenAIChat } from "."
|
||||
import { globalFetch, readImage } from "../globalApi.svelte"
|
||||
import { CharEmotion } from "../stores.svelte"
|
||||
import type { OpenAIChat } from "./index.svelte"
|
||||
import { processZip } from "./processzip"
|
||||
import { keiServerURL } from "../kei/kei"
|
||||
export async function stableDiff(currentChar:character,prompt:string){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
|
||||
if(db.sdProvider === ''){
|
||||
alertError("Stable diffusion is not set in settings.")
|
||||
@@ -56,7 +56,7 @@ export async function stableDiff(currentChar:character,prompt:string){
|
||||
}
|
||||
|
||||
export async function generateAIImage(genPrompt:string, currentChar:character, neg:string, returnSdData:string):Promise<string|false>{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
console.log(db.sdProvider)
|
||||
if(db.sdProvider === 'webui'){
|
||||
|
||||
@@ -490,7 +490,7 @@ export async function generateAIImage(genPrompt:string, currentChar:character, n
|
||||
}
|
||||
}
|
||||
if(db.sdProvider === 'kei'){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let auth = db?.account?.token
|
||||
if(!auth){
|
||||
db.account = JSON.parse(localStorage.getItem("fallbackRisuToken"))
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { get } from "svelte/store";
|
||||
import type { OpenAIChat } from ".";
|
||||
import { DataBase } from "../storage/database";
|
||||
import type { OpenAIChat } from "./index.svelte";
|
||||
import { getDatabase } from "../storage/database.svelte";
|
||||
import { getUserName } from "../util";
|
||||
|
||||
export function multiChatReplacer(){
|
||||
@@ -41,7 +40,7 @@ function appendWhitespace(prefix:string, seperator:string=" ") {
|
||||
return prefix
|
||||
}
|
||||
export function stringlizeChatOba(formated:OpenAIChat[], characterName:string, suggesting:boolean, continued:boolean){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let resultString:string[] = []
|
||||
let { systemPrefix, userPrefix, assistantPrefix, seperator } = db.ooba.formating;
|
||||
systemPrefix = systemPrefix ?? ""
|
||||
@@ -103,7 +102,7 @@ function toTitleCase(s:string){
|
||||
return s[0].toUpperCase() + s.slice(1).toLowerCase()
|
||||
}
|
||||
export function getStopStrings(suggesting:boolean=false){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let { userPrefix, seperator } = db.ooba.formating;
|
||||
if(!seperator){
|
||||
seperator = "\n"
|
||||
@@ -160,7 +159,7 @@ export function unstringlizeChat(text:string, formated:OpenAIChat[], char:string
|
||||
export function getUnstringlizerChunks(formated:OpenAIChat[], char:string, mode:'ain'|'normal' = 'normal'){
|
||||
let chunks:string[] = ["system note:", "system:","system note:", "system:"]
|
||||
let charNames:string[] = []
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(char){
|
||||
charNames.push(char)
|
||||
if(mode === 'ain'){
|
||||
@@ -212,7 +211,7 @@ export function getUnstringlizerChunks(formated:OpenAIChat[], char:string, mode:
|
||||
|
||||
export function stringlizeAINChat(formated:OpenAIChat[], char:string, continued: boolean){
|
||||
let resultString:string[] = []
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
|
||||
for(const form of formated){
|
||||
console.log(form)
|
||||
@@ -292,7 +291,7 @@ function extractAINOutputStrings(inputString:string, characters:string[]) {
|
||||
|
||||
export function unstringlizeAIN(data:string,formated:OpenAIChat[], char:string = ''){
|
||||
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const chunksResult = getUnstringlizerChunks(formated, char ,'ain')
|
||||
const chunks = chunksResult.chunks
|
||||
let result:['char'|'user',string][] = []
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Template } from '@huggingface/jinja';
|
||||
import type { OpenAIChat } from '..';
|
||||
import { get } from 'svelte/store';
|
||||
import { DataBase } from 'src/ts/storage/database';
|
||||
import { CurrentCharacter } from 'src/ts/stores';
|
||||
import type { OpenAIChat } from '../index.svelte';
|
||||
import { getCurrentCharacter, getDatabase } from 'src/ts/storage/database.svelte';
|
||||
import { getUserName } from 'src/ts/util';
|
||||
|
||||
export const chatTemplates = {
|
||||
@@ -30,13 +28,13 @@ export const applyChatTemplate = (messages:OpenAIChat[], arg:{
|
||||
type?: string
|
||||
custom?: string
|
||||
} = {}) => {
|
||||
const db = get(DataBase)
|
||||
const currentChar = get(CurrentCharacter)
|
||||
const db = getDatabase()
|
||||
const currentChar = getCurrentCharacter()
|
||||
const type = arg.type ?? db.instructChatTemplate
|
||||
if(!type){
|
||||
throw new Error('Template type is not set')
|
||||
}
|
||||
let clonedMessages = structuredClone(messages)
|
||||
let clonedMessages = safeStructuredClone(messages)
|
||||
const template = type === 'jinja' ? (new Template(arg.custom ?? db.JinjaTemplate)) :(new Template(chatTemplates[type]))
|
||||
let formatedMessages:{
|
||||
"role": 'user'|'assistant'|'system',
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { DataBase, setPreset, type botPreset, setDatabase } from "src/ts/storage/database";
|
||||
import { setPreset, type botPreset, setDatabase, getDatabase } from "src/ts/storage/database.svelte";
|
||||
import { defaultAutoSuggestPrefixOoba, defaultAutoSuggestPrompt, defaultAutoSuggestPromptOoba } from "src/ts/storage/defaultPrompts";
|
||||
import { get } from "svelte/store";
|
||||
import { prebuiltNAIpresets, prebuiltPresets } from "./templates";
|
||||
import { prebuiltPresets } from "./templates";
|
||||
import { alertConfirm, alertSelect } from "src/ts/alert";
|
||||
import { language } from "src/lang";
|
||||
|
||||
export async function setRecommended(model: string, ask:'ask'|'force') {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(!(recommendedPresetExist(model))){
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { risuChatParser } from "src/ts/parser"
|
||||
import { DataBase } from "src/ts/storage/database"
|
||||
import { get } from "svelte/store"
|
||||
import { risuChatParser } from "src/ts/parser.svelte"
|
||||
import { getDatabase } from "src/ts/storage/database.svelte"
|
||||
|
||||
export function convertInterfaceToSchema(int:string){
|
||||
if(!int.startsWith('interface ') && !int.startsWith('export interface ')){
|
||||
@@ -122,7 +121,7 @@ export function convertInterfaceToSchema(int:string){
|
||||
}
|
||||
|
||||
export function getOpenAIJSONSchema(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const schema = {
|
||||
"name": "format",
|
||||
"strict": db.strictJsonSchema,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Database } from 'src/ts/storage/database'
|
||||
import type { Database } from 'src/ts/storage/database.svelte'
|
||||
|
||||
export function templateCheck(db:Database){
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { botPreset } from "../../storage/database";
|
||||
import type { botPreset } from "../../storage/database.svelte";
|
||||
import type { NAISettings } from "../models/nai";
|
||||
|
||||
|
||||
@@ -757,7 +757,7 @@ export const prebuiltPresets:{OAI:botPreset,ooba:botPreset,NAI:botPreset,oobaRp:
|
||||
},
|
||||
{
|
||||
"type": "plain",
|
||||
"text": "</ROLEPLAY_INFO>",
|
||||
"text": "</ROLEPLAY_INFO>\n\n<RESPONSE_INSTRUCTION>\n[Narrative Techniques]\n• Use immersive third-person limited perspective\n• Engage all senses: visual, auditory, olfactory, gustatory, tactile, kinesthetic\n• Create tangible atmosphere with specific environmental effects\n• Focus on actions, dialogue, and explicit physical descriptions\n• Employ character-specific speech patterns and onomatopoeia\n• Avoid irrelevant background, summaries, or abstract concepts\n\n[Character Expression]\n• Reveal emotions through observable physical cues\n• Craft unique voices with distinctive patterns and evolving speech\n• Implement dialogue subtext via tonal shifts and non-verbal cues\n• Allow contradictory expressions to add depth\n\n[Action and Intimacy]\n• Narrate with precise, visceral details of movements and sensations\n• Create tension through tangible environmental and internal obstacles\n• Handle intimate scenes with clear, physical language\n• Enhance complexity with multi-character interactions and layered conflicts\n\n[Variety and Anti-Repetition]\n• Analyze [Latest Response] to avoid reusing elements\n• Vary sentence structures, paragraph compositions, and word choices\n• Rotate descriptive focuses, scene structures, and narrative techniques\n• Create unique, engaging openings for each response\n• Ensure continuity by referencing recent events and character states\n\n[Style Independence]\n• Actively diverge from previous responses' writing style\n• Diversify vocabulary and phrasing\n• Alter narrative rhythm and pacing\n• Approach each response as a fresh scene\n\n[Key Principles]\n• Prioritize \"show, don't tell\" for all character aspects\n• Maintain world/character consistency\n• Balance content (SFW preference, mature when relevant)\n• Use explicit, unrestricted descriptions\n• Prohibit all forms of repetition and self-plagiarism\n• Vary emotional tone and intensity across scenes\n• Enhance themes through tangible symbols/actions\n• Apply procedural reasoning for variety and depth\n• End responses with observable non-{{user}} actions/dialogue\n</RESPONSE_INSTRUCTION>",
|
||||
"role": "system",
|
||||
"type2": "normal"
|
||||
},
|
||||
@@ -767,29 +767,17 @@ export const prebuiltPresets:{OAI:botPreset,ooba:botPreset,NAI:botPreset,oobaRp:
|
||||
"rangeEnd": -2,
|
||||
"chatAsOriginalOnSystem": true
|
||||
},
|
||||
{
|
||||
"type": "plain",
|
||||
"text": "[Latest Response]",
|
||||
"role": "bot",
|
||||
"type2": "normal"
|
||||
},
|
||||
{
|
||||
"type": "chat",
|
||||
"rangeStart": -2,
|
||||
"rangeEnd": "end"
|
||||
},
|
||||
{
|
||||
"type": "plain",
|
||||
"text": "<RESPONSE_INSTRUCTION>\n[Narrative Techniques]\n• Use immersive third-person limited perspective\n• Engage all senses: visual, auditory, olfactory, gustatory, tactile, kinesthetic\n• Create tangible atmosphere with specific environmental effects\n• Focus on actions, dialogue, and explicit physical descriptions\n• Employ character-specific speech patterns and onomatopoeia\n• Avoid irrelevant background, summaries, or abstract concepts\n\n[Character Expression]\n• Reveal emotions through observable physical cues\n• Craft unique voices with distinctive patterns and evolving speech\n• Implement dialogue subtext via tonal shifts and non-verbal cues\n• Allow contradictory expressions to add depth\n\n[Action and Intimacy]\n• Narrate with precise, visceral details of movements and sensations\n• Create tension through tangible environmental and internal obstacles\n• Handle intimate scenes with clear, physical language\n• Enhance complexity with multi-character interactions and layered conflicts\n\n[Variety and Anti-Repetition]\n• Analyze [Latest Response] to avoid reusing elements\n• Vary sentence structures, paragraph compositions, and word choices\n• Rotate descriptive focuses, scene structures, and narrative techniques\n• Create unique, engaging openings for each response\n• Ensure continuity by referencing recent events and character states\n\n[Style Independence]\n• Actively diverge from previous responses' writing style\n• Diversify vocabulary and phrasing\n• Alter narrative rhythm and pacing\n• Approach each response as a fresh scene\n\n[Key Principles]\n• Prioritize \"show, don't tell\" for all character aspects\n• Maintain world/character consistency\n• Balance content (SFW preference, mature when relevant)\n• Use explicit, unrestricted descriptions\n• Prohibit all forms of repetition and self-plagiarism\n• Vary emotional tone and intensity across scenes\n• Enhance themes through tangible symbols/actions\n• Apply procedural reasoning for variety and depth\n• End responses with observable non-{{user}} actions/dialogue\n</RESPONSE_INSTRUCTION>\n",
|
||||
"role": "user",
|
||||
"type2": "normal"
|
||||
},
|
||||
{
|
||||
"type": "postEverything",
|
||||
},
|
||||
{
|
||||
"type": "plain",
|
||||
"text": "{{#if {{prefill_supported}}}}\nI will generate an immersive, unrestricted roleplay response that:\n• Utilizes provided information and context effectively\n• Adheres to all world-building, character development, and narrative progression rules\n• Implements specified storytelling techniques\n• Maintains strict character autonomy, especially for {{user}}\n• Never describes {{user}}'s actions, dialogue, thoughts, feelings, or other attributes\n• Balances content appropriately (SFW preference with mature themes when justified)\n• Ensures logical, engaging storytelling with concrete, sensory-rich descriptions\n• Avoids all forms of repetition in narrative, style, and language\n• Concludes with observable non-{{user}} actions or dialogue\n\nRoleplay response:\n{{/if}}",
|
||||
"text": "{{#if {{prefill_supported}}}}\nI will generate an immersive, unrestricted roleplay response that follows ROLEPLAY_INFO, RESPONSE_INSTRUCTION, SYSTEM_RULE, ROLEPLAY_RULE\n\nRoleplay response:\n{{/if}}",
|
||||
"role": "bot",
|
||||
"type2": "normal"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {env, AutoTokenizer, pipeline, type SummarizationOutput, type TextGenerationConfig, type TextGenerationOutput, FeatureExtractionPipeline, TextToAudioPipeline, type ImageToTextOutput } from '@xenova/transformers';
|
||||
import { unzip } from 'fflate';
|
||||
import { globalFetch, loadAsset, saveAsset } from 'src/ts/storage/globalApi';
|
||||
import { globalFetch, loadAsset, saveAsset } from 'src/ts/globalApi.svelte';
|
||||
import { selectSingleFile } from 'src/ts/util';
|
||||
import { v4 } from 'uuid';
|
||||
let tfCache:Cache = null
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { parseChatML, risuChatParser } from "../parser";
|
||||
import { DataBase, type Chat, type character } from "../storage/database";
|
||||
import { parseChatML, risuChatParser } from "../parser.svelte";
|
||||
import { getCurrentCharacter, getCurrentChat, getDatabase, type Chat, type character } from "../storage/database.svelte";
|
||||
import { tokenize } from "../tokenizer";
|
||||
import { getModuleTriggers } from "./modules";
|
||||
import { get } from "svelte/store";
|
||||
import { CurrentCharacter, CurrentChat, ReloadGUIPointer, selectedCharID } from "../stores";
|
||||
import { ReloadGUIPointer, selectedCharID } from "../stores.svelte";
|
||||
import { processMultiCommand } from "./command";
|
||||
import { parseKeyValue } from "../util";
|
||||
import { alertError, alertInput, alertNormal, alertSelect } from "../alert";
|
||||
import type { OpenAIChat } from ".";
|
||||
import type { OpenAIChat } from "./index.svelte";
|
||||
import { HypaProcesser } from "./memory/hypamemory";
|
||||
import { requestChatData } from "./request";
|
||||
import { generateAIImage } from "./stableDiff";
|
||||
@@ -152,12 +152,12 @@ export async function runTrigger(char:character,mode:triggerMode, arg:{
|
||||
manualName?: string
|
||||
}){
|
||||
arg.recursiveCount ??= 0
|
||||
char = structuredClone(char)
|
||||
char = safeStructuredClone(char)
|
||||
let varChanged = false
|
||||
let stopSending = arg.stopSending ?? false
|
||||
const CharacterlowLevelAccess = char.lowLevelAccess ?? false
|
||||
let sendAIprompt = false
|
||||
const currentChat = get(CurrentChat)
|
||||
const currentChat = getCurrentChat()
|
||||
let additonalSysPrompt:additonalSysPrompt = arg.additonalSysPrompt ?? {
|
||||
start:'',
|
||||
historyend: '',
|
||||
@@ -167,9 +167,9 @@ export async function runTrigger(char:character,mode:triggerMode, arg:{
|
||||
v.lowLevelAccess = CharacterlowLevelAccess
|
||||
return v
|
||||
}).concat(getModuleTriggers())
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const defaultVariables = parseKeyValue(char.defaultVariables).concat(parseKeyValue(db.templateDefaultVariables))
|
||||
let chat = structuredClone(arg.chat ?? char.chats[char.chatPage])
|
||||
let chat = safeStructuredClone(arg.chat ?? char.chats[char.chatPage])
|
||||
if((!triggers) || (triggers.length === 0)){
|
||||
return null
|
||||
}
|
||||
@@ -190,8 +190,8 @@ export async function runTrigger(char:character,mode:triggerMode, arg:{
|
||||
|
||||
function setVar(key:string, value:string){
|
||||
const selectedCharId = get(selectedCharID)
|
||||
const currentCharacter = get(CurrentCharacter)
|
||||
const db = get(DataBase)
|
||||
const currentCharacter = getCurrentCharacter()
|
||||
const db = getDatabase()
|
||||
varChanged = true
|
||||
chat.scriptstate ??= {}
|
||||
chat.scriptstate['$' + key] = value
|
||||
@@ -517,7 +517,7 @@ export async function runTrigger(char:character,mode:triggerMode, arg:{
|
||||
if(triggerCodeResult.stopSending){
|
||||
stopSending = true
|
||||
}
|
||||
chat = triggerCodeResult.chat
|
||||
chat = getCurrentChat()
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -535,7 +535,7 @@ export async function runTrigger(char:character,mode:triggerMode, arg:{
|
||||
caculatedTokens += await tokenize(additonalSysPrompt.promptend)
|
||||
}
|
||||
if(varChanged){
|
||||
const currentChat = get(CurrentChat)
|
||||
const currentChat = getCurrentChat()
|
||||
currentChat.scriptstate = chat.scriptstate
|
||||
ReloadGUIPointer.set(get(ReloadGUIPointer) + 1)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { get } from "svelte/store";
|
||||
import { alertError } from "../alert";
|
||||
import { DataBase, type character } from "../storage/database";
|
||||
import { getCurrentCharacter, getDatabase, type character } from "../storage/database.svelte";
|
||||
import { runTranslator, translateVox } from "../translator/translator";
|
||||
import { globalFetch, loadAsset } from "../storage/globalApi";
|
||||
import { globalFetch, loadAsset } from "../globalApi.svelte";
|
||||
import { language } from "src/lang";
|
||||
import { getCurrentCharacter, sleep } from "../util";
|
||||
import { registerOnnxModel, runVITS } from "./transformers";
|
||||
import { sleep } from "../util";
|
||||
import { runVITS } from "./transformers";
|
||||
|
||||
let sourceNode:AudioBufferSourceNode = null
|
||||
|
||||
@@ -23,7 +22,7 @@ export async function sayTTS(character:character,text:string) {
|
||||
return
|
||||
}
|
||||
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
text = text.replace(/\*/g,'')
|
||||
|
||||
if(character.ttsReadOnlyQuoted){
|
||||
@@ -311,6 +310,49 @@ export async function sayTTS(character:character,text:string) {
|
||||
throw new Error(text);
|
||||
}
|
||||
}
|
||||
case 'fishspeech':{
|
||||
if (character.fishSpeechConfig.model._id === ''){
|
||||
throw new Error('FishSpeech Model is not selected')
|
||||
}
|
||||
const audioContext = new AudioContext();
|
||||
|
||||
const body = {
|
||||
text: text,
|
||||
reference_id: character.fishSpeechConfig.model._id,
|
||||
chunk_length: character.fishSpeechConfig.chunk_length,
|
||||
normalize: character.fishSpeechConfig.normalize,
|
||||
format: 'mp3',
|
||||
mp3_bitrate: 192,
|
||||
}
|
||||
|
||||
|
||||
console.log(body)
|
||||
|
||||
const response = await globalFetch(`https://api.fish.audio/v1/tts`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${db.fishSpeechKey}`
|
||||
},
|
||||
body: body,
|
||||
rawResponse: true,
|
||||
})
|
||||
console.log(response)
|
||||
|
||||
if (response.ok) {
|
||||
const audioBuffer = response.data.buffer;
|
||||
audioContext.decodeAudioData(audioBuffer, (decodedData) => {
|
||||
const sourceNode = audioContext.createBufferSource();
|
||||
sourceNode.buffer = decodedData;
|
||||
sourceNode.connect(audioContext.destination);
|
||||
sourceNode.start();
|
||||
});
|
||||
} else {
|
||||
const textBuffer: Uint8Array = response.data.buffer
|
||||
const text = Buffer.from(textBuffer).toString('utf-8')
|
||||
throw new Error(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
alertError(`TTS Error: ${error}`)
|
||||
@@ -340,7 +382,7 @@ export function getWebSpeechTTSVoices() {
|
||||
}
|
||||
|
||||
export async function getElevenTTSVoices() {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
|
||||
const data = await fetch('https://api.elevenlabs.io/v1/voices', {
|
||||
headers: {
|
||||
@@ -354,7 +396,7 @@ export async function getElevenTTSVoices() {
|
||||
}
|
||||
|
||||
export async function getVOICEVOXVoices() {
|
||||
const db = get(DataBase);
|
||||
const db = getDatabase();
|
||||
const speakerData = await fetch(`${db.voicevoxUrl}/speakers`)
|
||||
const speakerList = await speakerData.json()
|
||||
const speakersInfo = speakerList.map((speaker) => {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { get } from "svelte/store";
|
||||
import { exportCharacterCard } from "./characterCards";
|
||||
import { VirtualWriter, isTauri, openURL } from "./storage/globalApi";
|
||||
import { sleep } from "./util";
|
||||
import { CurrentCharacter } from "./stores";
|
||||
import { DataBase, type character } from "./storage/database";
|
||||
import { VirtualWriter, isTauri, openURL } from "./globalApi.svelte";
|
||||
import { getCurrentCharacter, getDatabase, type character } from "./storage/database.svelte";
|
||||
import { alertStore } from "./alert";
|
||||
|
||||
let pong = false;
|
||||
@@ -17,7 +15,7 @@ window.addEventListener("message", (event) => {
|
||||
});
|
||||
|
||||
export async function shareRealmCardData():Promise<{ name: ArrayBuffer; data: ArrayBuffer; }> {
|
||||
const char = structuredClone(get(CurrentCharacter)) as character
|
||||
const char = safeStructuredClone(getCurrentCharacter({snapshot:true})) as character
|
||||
const trimedName = char.name.replace(/[^a-zA-Z0-9]/g, '') || 'character';
|
||||
const writer = new VirtualWriter()
|
||||
const namebuf = new TextEncoder().encode(trimedName + '.png')
|
||||
@@ -33,8 +31,8 @@ export async function shareRealmCardData():Promise<{ name: ArrayBuffer; data: Ar
|
||||
}
|
||||
|
||||
export async function openRealm(name:string,data:ArrayBuffer) {
|
||||
const tk = get(DataBase)?.account?.token;
|
||||
const id = get(DataBase)?.account?.id
|
||||
const tk = getDatabase()?.account?.token;
|
||||
const id = getDatabase()?.account?.id
|
||||
const trimedName = name.replace(/[^a-zA-Z0-9]/g, '') || 'character';
|
||||
const filedata = encodeURIComponent(Buffer.from(data).toString('base64')) + `&${trimedName}.png`;
|
||||
const url = `https://realm.risuai.net/upload?token=${tk}&token_id=${id}#filedata=${filedata}`
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { get, writable } from "svelte/store"
|
||||
import { DataBase } from "./database"
|
||||
import { writable } from "svelte/store"
|
||||
import { getDatabase } from "./database.svelte"
|
||||
import { hubURL } from "../characterCards"
|
||||
import localforage from "localforage"
|
||||
import { alertError, alertLogin, alertStore, alertWait } from "../alert"
|
||||
import { forageStorage, getUnpargeables, replaceDbResources } from "./globalApi"
|
||||
import { encodeRisuSave } from "./risuSave"
|
||||
import { alertLogin, alertNormalWait, alertStore, alertWait } from "../alert"
|
||||
import { forageStorage, getUnpargeables } from "../globalApi.svelte"
|
||||
import { encodeRisuSaveLegacy } from "./risuSave"
|
||||
import { v4 } from "uuid"
|
||||
import { language } from "src/lang"
|
||||
import { sleep } from "../util"
|
||||
|
||||
export const AccountWarning = writable('')
|
||||
const risuSession = Date.now().toFixed(0)
|
||||
const cachedForage = localforage.createInstance({name: "risuaiAccountCached"})
|
||||
|
||||
let seenWarnings:string[] = []
|
||||
|
||||
@@ -20,7 +22,20 @@ export class AccountStorage{
|
||||
async setItem(key:string, value:Uint8Array) {
|
||||
this.checkAuth()
|
||||
let da:Response
|
||||
|
||||
let daText:string|undefined = undefined
|
||||
const getDaText = async () => {
|
||||
if(daText === undefined){
|
||||
daText = await da.text()
|
||||
}
|
||||
return daText
|
||||
}
|
||||
|
||||
|
||||
while((!da) || da.status === 403){
|
||||
|
||||
const saveDate = Date.now().toFixed(0)
|
||||
|
||||
da = await fetch(hubURL + '/api/account/write', {
|
||||
method: "POST",
|
||||
body: value,
|
||||
@@ -29,11 +44,18 @@ export class AccountStorage{
|
||||
'x-risu-key': key,
|
||||
'x-risu-auth': this.auth,
|
||||
'X-Format': 'nocheck',
|
||||
'x-risu-session': risuSession
|
||||
'x-risu-session': risuSession,
|
||||
'x-risu-save-date': saveDate
|
||||
}
|
||||
})
|
||||
if(key === 'database/database.bin'){
|
||||
cachedForage.setItem(key, value).then(() => {
|
||||
cachedForage.setItem(key + '__date', saveDate)
|
||||
})
|
||||
}
|
||||
|
||||
if(da.headers.get('Content-Type') === 'application/json'){
|
||||
const json = (await da.json())
|
||||
const json = JSON.parse(await getDaText())
|
||||
if(json?.warning){
|
||||
if(!seenWarnings.includes(json.warning)){
|
||||
seenWarnings.push(json.warning)
|
||||
@@ -41,8 +63,10 @@ export class AccountStorage{
|
||||
}
|
||||
}
|
||||
if(json?.reloadSession){
|
||||
alertWait(language.reloadSession)
|
||||
location.reload()
|
||||
alertNormalWait(language.activeTabChange).then(() => {
|
||||
location.reload()
|
||||
})
|
||||
await sleep(100000000) // wait forever
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -59,9 +83,9 @@ export class AccountStorage{
|
||||
}
|
||||
}
|
||||
if(da.status < 200 || da.status >= 300){
|
||||
throw await da.text()
|
||||
throw await getDaText()
|
||||
}
|
||||
return await da.text()
|
||||
return await getDaText()
|
||||
}
|
||||
async getItem(key:string):Promise<Buffer> {
|
||||
this.checkAuth()
|
||||
@@ -72,13 +96,16 @@ export class AccountStorage{
|
||||
}
|
||||
}
|
||||
let da:Response
|
||||
const saveDate = await cachedForage.getItem(key + '__date') as number|undefined
|
||||
const perf = performance.now()
|
||||
while((!da) || da.status === 403){
|
||||
da = await fetch(hubURL + '/api/account/read/' + Buffer.from(key ,'utf-8').toString('hex') +
|
||||
(key.includes('database') ? ('|' + v4()) : ''), {
|
||||
method: "GET",
|
||||
headers: {
|
||||
'x-risu-key': key,
|
||||
'x-risu-auth': this.auth
|
||||
'x-risu-auth': this.auth,
|
||||
'x-risu-save-date': (saveDate || 0).toString()
|
||||
}
|
||||
})
|
||||
if(da.status === 403){
|
||||
@@ -86,6 +113,18 @@ export class AccountStorage{
|
||||
this.checkAuth()
|
||||
}
|
||||
}
|
||||
if(da.status === 303){
|
||||
console.log(performance.now() - perf)
|
||||
const data = await da.json()
|
||||
if(data.match){
|
||||
const c = Buffer.from(await cachedForage.getItem(key))
|
||||
return c
|
||||
}
|
||||
else{
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
if(da.status < 200 || da.status >= 300){
|
||||
throw await da.text()
|
||||
}
|
||||
@@ -99,7 +138,7 @@ export class AccountStorage{
|
||||
return Buffer.from(ab)
|
||||
}
|
||||
async keys():Promise<string[]>{
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
return getUnpargeables(db, 'pure')
|
||||
}
|
||||
async removeItem(key:string){
|
||||
@@ -107,7 +146,7 @@ export class AccountStorage{
|
||||
}
|
||||
|
||||
private checkAuth(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
this.auth = db?.account?.token
|
||||
if(!this.auth){
|
||||
db.account = JSON.parse(localStorage.getItem("fallbackRisuToken"))
|
||||
@@ -122,7 +161,7 @@ export class AccountStorage{
|
||||
|
||||
export async function unMigrationAccount() {
|
||||
const keys = await forageStorage.keys()
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let i = 0;
|
||||
const MigrationStorage = localforage.createInstance({name: "risuai"})
|
||||
|
||||
@@ -136,7 +175,7 @@ export async function unMigrationAccount() {
|
||||
}
|
||||
|
||||
db.account = null
|
||||
await MigrationStorage.setItem('database/database.bin', encodeRisuSave(db))
|
||||
await MigrationStorage.setItem('database/database.bin', encodeRisuSaveLegacy(db))
|
||||
|
||||
alertStore.set({
|
||||
type: "none",
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import localforage from "localforage"
|
||||
import { isNodeServer, replaceDbResources } from "./globalApi"
|
||||
import { isNodeServer, replaceDbResources } from "../globalApi.svelte"
|
||||
import { NodeStorage } from "./nodeStorage"
|
||||
import { OpfsStorage } from "./opfsStorage"
|
||||
import { alertInput, alertSelect, alertStore } from "../alert"
|
||||
import { get } from "svelte/store"
|
||||
import { DataBase, type Database } from "./database"
|
||||
import { getDatabase, type Database } from "./database.svelte"
|
||||
import { AccountStorage } from "./accountStorage"
|
||||
import { decodeRisuSave, encodeRisuSave } from "./risuSave";
|
||||
import { decodeRisuSave, encodeRisuSaveLegacy } from "./risuSave";
|
||||
import { language } from "src/lang"
|
||||
import { MobileStorage } from "./mobileStorage"
|
||||
import { Capacitor } from "@capacitor/core"
|
||||
@@ -40,7 +39,7 @@ export class AutoStorage{
|
||||
}
|
||||
|
||||
async checkAccountSync(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(this.isAccount){
|
||||
return true
|
||||
}
|
||||
@@ -89,10 +88,10 @@ export class AutoStorage{
|
||||
}
|
||||
|
||||
const dba = replaceDbResources(db, replaced)
|
||||
const comp = encodeRisuSave(dba, 'compression')
|
||||
const comp = encodeRisuSaveLegacy(dba, 'compression')
|
||||
//try decoding
|
||||
try {
|
||||
const z:Database = decodeRisuSave(comp)
|
||||
const z:Database = await decodeRisuSave(comp)
|
||||
if(z.formatversion){
|
||||
await accountStorage.setItem('database/database.bin', comp)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
export const DataBase = writable({} as any as Database)
|
||||
export const loadedStore = writable(false)
|
||||
export let appVer = "134.1.0"
|
||||
export let webAppSubVer = ''
|
||||
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { checkNullish, decryptBuffer, encryptBuffer, selectSingleFile } from '../util';
|
||||
import { changeLanguage, language } from '../../lang';
|
||||
import type { RisuPlugin } from '../plugins/plugins';
|
||||
import type {triggerscript as triggerscriptMain} from '../process/triggers';
|
||||
import { downloadFile, saveAsset as saveImageGlobal } from './globalApi';
|
||||
import { downloadFile, saveAsset as saveImageGlobal } from '../globalApi.svelte';
|
||||
import { defaultAutoSuggestPrompt, defaultJailbreak, defaultMainPrompt } from './defaultPrompts';
|
||||
import { alertNormal, alertSelect } from '../alert';
|
||||
import type { NAISettings } from '../process/models/nai';
|
||||
@@ -17,6 +12,10 @@ 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 webAppSubVer = ''
|
||||
|
||||
|
||||
export function setDatabase(data:Database){
|
||||
if(checkNullish(data.characters)){
|
||||
data.characters = []
|
||||
@@ -305,6 +304,7 @@ export function setDatabase(data:Database){
|
||||
data.sendWithEnter ??= true
|
||||
data.autoSuggestPrompt ??= defaultAutoSuggestPrompt
|
||||
data.autoSuggestPrefix ??= ""
|
||||
data.OAIPrediction ??= ''
|
||||
data.autoSuggestClean ??= true
|
||||
data.imageCompression ??= true
|
||||
if(!data.formatingOrder.includes('personaPrompt')){
|
||||
@@ -319,16 +319,16 @@ export function setDatabase(data:Database){
|
||||
largePortrait: false
|
||||
}]
|
||||
data.classicMaxWidth ??= false
|
||||
data.ooba ??= structuredClone(defaultOoba)
|
||||
data.ainconfig ??= structuredClone(defaultAIN)
|
||||
data.ooba ??= safeStructuredClone(defaultOoba)
|
||||
data.ainconfig ??= safeStructuredClone(defaultAIN)
|
||||
data.openrouterKey ??= ''
|
||||
data.openrouterRequestModel ??= 'openai/gpt-3.5-turbo'
|
||||
data.toggleConfirmRecommendedPreset ??= true
|
||||
data.officialplugins ??= {}
|
||||
data.NAIsettings ??= structuredClone(prebuiltNAIpresets)
|
||||
data.NAIsettings ??= safeStructuredClone(prebuiltNAIpresets)
|
||||
data.assetWidth ??= -1
|
||||
data.animationSpeed ??= 0.4
|
||||
data.colorScheme ??= structuredClone(defaultColorScheme)
|
||||
data.colorScheme ??= safeStructuredClone(defaultColorScheme)
|
||||
data.colorSchemeName ??= 'default'
|
||||
data.NAIsettings.starter ??= ""
|
||||
data.hypaModel ??= 'MiniLM'
|
||||
@@ -354,6 +354,7 @@ export function setDatabase(data:Database){
|
||||
data.newOAIHandle ??= true
|
||||
data.gptVisionQuality ??= 'low'
|
||||
data.huggingfaceKey ??= ''
|
||||
data.fishSpeechKey ??= ''
|
||||
data.statistics ??= {}
|
||||
data.reverseProxyOobaArgs ??= {
|
||||
mode: 'instruct'
|
||||
@@ -445,10 +446,86 @@ export function setDatabase(data:Database){
|
||||
}
|
||||
data.customQuotes ??= false
|
||||
data.customQuotesData ??= ['“','”','‘','’']
|
||||
data.groupOtherBotRole ??= 'user'
|
||||
data.customGUI ??= ''
|
||||
data.customAPIFormat ??= LLMFormat.OpenAICompatible
|
||||
data.systemContentReplacement ??= `system: {{slot}}`
|
||||
data.systemRoleReplacement ??= 'user'
|
||||
data.vertexAccessToken ??= ''
|
||||
data.vertexAccessTokenExpires ??= 0
|
||||
data.vertexClientEmail ??= ''
|
||||
data.vertexPrivateKey ??= ''
|
||||
data.seperateParametersEnabled ??= false
|
||||
data.seperateParameters = {
|
||||
memory: {},
|
||||
emotion: {},
|
||||
translate: {},
|
||||
otherAx: {}
|
||||
}
|
||||
changeLanguage(data.language)
|
||||
DataBase.set(data)
|
||||
setDatabaseLite(data)
|
||||
}
|
||||
|
||||
export function setDatabaseLite(data:Database){
|
||||
if(import.meta.env.DEV){
|
||||
console.trace('setDatabaseLite executed')
|
||||
}
|
||||
DBState.db = data
|
||||
}
|
||||
|
||||
interface getDatabaseOptions{
|
||||
snapshot?:boolean
|
||||
}
|
||||
|
||||
export function getDatabase(options:getDatabaseOptions = {}):Database{
|
||||
if(options.snapshot){
|
||||
return $state.snapshot(DBState.db) as Database
|
||||
}
|
||||
return DBState.db as Database
|
||||
}
|
||||
|
||||
export function getCurrentCharacter(options:getDatabaseOptions = {}):character|groupChat{
|
||||
const db = getDatabase(options)
|
||||
if(!db.characters){
|
||||
db.characters = []
|
||||
}
|
||||
const char = db.characters?.[get(selectedCharID)]
|
||||
return char
|
||||
}
|
||||
|
||||
export function setCurrentCharacter(char:character|groupChat){
|
||||
if(!DBState.db.characters){
|
||||
DBState.db.characters = []
|
||||
}
|
||||
DBState.db.characters[get(selectedCharID)] = char
|
||||
}
|
||||
|
||||
export function getCharacterByIndex(index:number,options:getDatabaseOptions = {}):character|groupChat{
|
||||
const db = getDatabase(options)
|
||||
if(!db.characters){
|
||||
db.characters = []
|
||||
}
|
||||
const char = db.characters?.[index]
|
||||
return char
|
||||
}
|
||||
|
||||
export function setCharacterByIndex(index:number,char:character|groupChat){
|
||||
if(!DBState.db.characters){
|
||||
DBState.db.characters = []
|
||||
}
|
||||
DBState.db.characters[index] = char
|
||||
}
|
||||
|
||||
export function getCurrentChat(){
|
||||
const char = getCurrentCharacter()
|
||||
return char?.chats[char.chatPage]
|
||||
}
|
||||
|
||||
export function setCurrentChat(chat:Chat){
|
||||
const char = getCurrentCharacter()
|
||||
char.chats[char.chatPage] = chat
|
||||
setCurrentCharacter(char)
|
||||
}
|
||||
|
||||
export interface Database{
|
||||
characters: (character|groupChat)[],
|
||||
@@ -654,6 +731,7 @@ export interface Database{
|
||||
tpo?:boolean
|
||||
automark?:boolean
|
||||
huggingfaceKey:string
|
||||
fishSpeechKey:string
|
||||
allowAllExtentionFiles?:boolean
|
||||
translatorPrompt:string
|
||||
translatorMaxResponse:number
|
||||
@@ -751,6 +829,40 @@ export interface Database{
|
||||
}
|
||||
customQuotes:boolean
|
||||
customQuotesData?:[string, string, string, string]
|
||||
groupTemplate?:string
|
||||
groupOtherBotRole?:string
|
||||
customGUI:string
|
||||
guiHTML:string
|
||||
logShare:boolean
|
||||
OAIPrediction:string
|
||||
customAPIFormat:LLMFormat
|
||||
systemContentReplacement:string
|
||||
systemRoleReplacement:'user'|'assistant'
|
||||
vertexPrivateKey: string
|
||||
vertexClientEmail: string
|
||||
vertexAccessToken: string
|
||||
vertexAccessTokenExpires: number
|
||||
seperateParametersEnabled:boolean
|
||||
seperateParameters:{
|
||||
memory: SeparateParameters,
|
||||
emotion: SeparateParameters,
|
||||
translate: SeparateParameters,
|
||||
otherAx: SeparateParameters
|
||||
}
|
||||
translateBeforeHTMLFormatting:boolean
|
||||
autoTranslateCachedOnly:boolean
|
||||
lightningRealmImport:boolean
|
||||
}
|
||||
|
||||
interface SeparateParameters{
|
||||
temperature?:number
|
||||
top_k?:number
|
||||
repetition_penalty?:number
|
||||
min_p?:number
|
||||
top_a?:number
|
||||
top_p?:number
|
||||
frequency_penalty?:number
|
||||
presence_penalty?:number
|
||||
}
|
||||
|
||||
export interface customscript{
|
||||
@@ -864,6 +976,16 @@ export interface character{
|
||||
top_k?:number
|
||||
text_split_method?: "cut0" | "cut1" | "cut2" | "cut3" | "cut4" | "cut5"
|
||||
}
|
||||
fishSpeechConfig?:{
|
||||
model?: {
|
||||
_id:string
|
||||
title:string
|
||||
description:string
|
||||
},
|
||||
chunk_length:number,
|
||||
normalize:boolean,
|
||||
|
||||
}
|
||||
supaMemory?:boolean
|
||||
additionalAssets?:[string, string, string][]
|
||||
ttsReadOnlyQuoted?:boolean
|
||||
@@ -905,6 +1027,7 @@ export interface character{
|
||||
lowLevelAccess?:boolean
|
||||
hideChatIcon?:boolean
|
||||
lastInteraction?:number
|
||||
translatorNote?:string
|
||||
}
|
||||
|
||||
|
||||
@@ -916,7 +1039,7 @@ export interface loreSettings{
|
||||
}
|
||||
|
||||
|
||||
export interface groupChat{
|
||||
export interface groupChat{
|
||||
type: 'group'
|
||||
image?:string
|
||||
firstMessage:string
|
||||
@@ -954,6 +1077,30 @@ export interface groupChat{
|
||||
lowLevelAccess?:boolean
|
||||
hideChatIcon?:boolean
|
||||
lastInteraction?:number
|
||||
|
||||
//lazy hack for typechecking
|
||||
voicevoxConfig?:any
|
||||
ttsSpeech?:string
|
||||
naittsConfig?:any
|
||||
oaiVoice?:string
|
||||
hfTTS?: any
|
||||
vits?: OnnxModelFiles
|
||||
gptSoVitsConfig?:any
|
||||
fishSpeechConfig?:any
|
||||
ttsReadOnlyQuoted?:boolean
|
||||
exampleMessage?:string
|
||||
systemPrompt?:string
|
||||
replaceGlobalNote?:string
|
||||
additionalText?:string
|
||||
personality?:string
|
||||
scenario?:string
|
||||
translatorNote?:string
|
||||
additionalData?: any
|
||||
depth_prompt?: { depth: number, prompt: string }
|
||||
additionalAssets?:[string, string, string][]
|
||||
utilityBot?:boolean
|
||||
license?:string
|
||||
realmId:string
|
||||
}
|
||||
|
||||
export interface botPreset{
|
||||
@@ -1011,6 +1158,19 @@ export interface botPreset{
|
||||
jsonSchema?:string
|
||||
strictJsonSchema?:boolean
|
||||
extractJson?:string
|
||||
groupTemplate?:string
|
||||
groupOtherBotRole?:string
|
||||
seperateParametersEnabled?:boolean
|
||||
seperateParameters?:{
|
||||
memory: SeparateParameters,
|
||||
emotion: SeparateParameters,
|
||||
translate: SeparateParameters,
|
||||
otherAx: SeparateParameters
|
||||
}
|
||||
customAPIFormat?:LLMFormat
|
||||
systemContentReplacement?: string
|
||||
systemRoleReplacement?: 'user'|'assistant'
|
||||
openAIPrediction?: string
|
||||
}
|
||||
|
||||
|
||||
@@ -1222,8 +1382,8 @@ export const presetTemplate:botPreset = {
|
||||
promptPreprocess: false,
|
||||
proxyKey: '',
|
||||
bias: [],
|
||||
ooba: structuredClone(defaultOoba),
|
||||
ainconfig: structuredClone(defaultAIN),
|
||||
ooba: safeStructuredClone(defaultOoba),
|
||||
ainconfig: safeStructuredClone(defaultAIN),
|
||||
reverseProxyOobaArgs: {
|
||||
mode: 'instruct'
|
||||
},
|
||||
@@ -1242,11 +1402,11 @@ const defaultSdData:[string,string][] = [
|
||||
]
|
||||
|
||||
export const defaultSdDataFunc = () =>{
|
||||
return structuredClone(defaultSdData)
|
||||
return safeStructuredClone(defaultSdData)
|
||||
}
|
||||
|
||||
export function saveCurrentPreset(){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let pres = db.botPresets
|
||||
pres[db.botPresetsId] = {
|
||||
name: pres[db.botPresetsId].name,
|
||||
@@ -1272,20 +1432,20 @@ export function saveCurrentPreset(){
|
||||
bias: db.bias,
|
||||
koboldURL: db.koboldURL,
|
||||
proxyKey: db.proxyKey,
|
||||
ooba: structuredClone(db.ooba),
|
||||
ainconfig: structuredClone(db.ainconfig),
|
||||
ooba: safeStructuredClone(db.ooba),
|
||||
ainconfig: safeStructuredClone(db.ainconfig),
|
||||
proxyRequestModel: db.proxyRequestModel,
|
||||
openrouterRequestModel: db.openrouterRequestModel,
|
||||
NAISettings: structuredClone(db.NAIsettings),
|
||||
NAISettings: safeStructuredClone(db.NAIsettings),
|
||||
promptTemplate: db.promptTemplate ?? null,
|
||||
NAIadventure: db.NAIadventure ?? false,
|
||||
NAIappendName: db.NAIappendName ?? false,
|
||||
localStopStrings: db.localStopStrings,
|
||||
autoSuggestPrompt: db.autoSuggestPrompt,
|
||||
customProxyRequestModel: db.customProxyRequestModel,
|
||||
reverseProxyOobaArgs: structuredClone(db.reverseProxyOobaArgs) ?? null,
|
||||
reverseProxyOobaArgs: safeStructuredClone(db.reverseProxyOobaArgs) ?? null,
|
||||
top_p: db.top_p ?? 1,
|
||||
promptSettings: structuredClone(db.promptSettings) ?? null,
|
||||
promptSettings: safeStructuredClone(db.promptSettings) ?? null,
|
||||
repetition_penalty: db.repetition_penalty,
|
||||
min_p: db.min_p,
|
||||
top_a: db.top_a,
|
||||
@@ -1301,6 +1461,14 @@ export function saveCurrentPreset(){
|
||||
jsonSchema:db.jsonSchema ?? '',
|
||||
strictJsonSchema:db.strictJsonSchema ?? true,
|
||||
extractJson:db.extractJson ?? '',
|
||||
groupOtherBotRole: db.groupOtherBotRole ?? 'user',
|
||||
groupTemplate: db.groupTemplate ?? '',
|
||||
seperateParametersEnabled: db.seperateParametersEnabled ?? false,
|
||||
seperateParameters: safeStructuredClone(db.seperateParameters),
|
||||
openAIPrediction: db.OAIPrediction,
|
||||
customAPIFormat: safeStructuredClone(db.customAPIFormat),
|
||||
systemContentReplacement: db.systemContentReplacement,
|
||||
systemRoleReplacement: db.systemRoleReplacement,
|
||||
}
|
||||
db.botPresets = pres
|
||||
setDatabase(db)
|
||||
@@ -1308,9 +1476,9 @@ export function saveCurrentPreset(){
|
||||
|
||||
export function copyPreset(id:number){
|
||||
saveCurrentPreset()
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let pres = db.botPresets
|
||||
const newPres = structuredClone(pres[id])
|
||||
const newPres = safeStructuredClone(pres[id])
|
||||
newPres.name += " Copy"
|
||||
db.botPresets.push(newPres)
|
||||
setDatabase(db)
|
||||
@@ -1320,7 +1488,7 @@ export function changeToPreset(id =0, savecurrent = true){
|
||||
if(savecurrent){
|
||||
saveCurrentPreset()
|
||||
}
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let pres = db.botPresets
|
||||
const newPres = pres[id]
|
||||
db.botPresetsId = id
|
||||
@@ -1350,8 +1518,8 @@ export function setPreset(db:Database, newPres: botPreset){
|
||||
db.bias = newPres.bias ?? db.bias
|
||||
db.koboldURL = newPres.koboldURL ?? db.koboldURL
|
||||
db.proxyKey = newPres.proxyKey ?? db.proxyKey
|
||||
db.ooba = structuredClone(newPres.ooba ?? db.ooba)
|
||||
db.ainconfig = structuredClone(newPres.ainconfig ?? db.ainconfig)
|
||||
db.ooba = safeStructuredClone(newPres.ooba ?? db.ooba)
|
||||
db.ainconfig = safeStructuredClone(newPres.ainconfig ?? db.ainconfig)
|
||||
db.openrouterRequestModel = newPres.openrouterRequestModel ?? db.openrouterRequestModel
|
||||
db.proxyRequestModel = newPres.proxyRequestModel ?? db.proxyRequestModel
|
||||
db.NAIsettings = newPres.NAISettings ?? db.NAIsettings
|
||||
@@ -1366,12 +1534,12 @@ export function setPreset(db:Database, newPres: botPreset){
|
||||
db.NAIsettings.mirostat_lr ??= 1
|
||||
db.localStopStrings = newPres.localStopStrings
|
||||
db.customProxyRequestModel = newPres.customProxyRequestModel ?? ''
|
||||
db.reverseProxyOobaArgs = structuredClone(newPres.reverseProxyOobaArgs) ?? {
|
||||
db.reverseProxyOobaArgs = safeStructuredClone(newPres.reverseProxyOobaArgs) ?? {
|
||||
mode: 'instruct'
|
||||
}
|
||||
db.top_p = newPres.top_p ?? 1
|
||||
//@ts-ignore //for legacy mistpings
|
||||
db.promptSettings = structuredClone(newPres.promptSettings) ?? {
|
||||
db.promptSettings = safeStructuredClone(newPres.promptSettings) ?? {
|
||||
assistantPrefill: '',
|
||||
postEndInnerFormat: '',
|
||||
sendChatAsSystem: false,
|
||||
@@ -1393,6 +1561,19 @@ export function setPreset(db:Database, newPres: botPreset){
|
||||
db.jsonSchema = newPres.jsonSchema ?? ''
|
||||
db.strictJsonSchema = newPres.strictJsonSchema ?? true
|
||||
db.extractJson = newPres.extractJson ?? ''
|
||||
db.groupOtherBotRole = newPres.groupOtherBotRole ?? 'user'
|
||||
db.groupTemplate = newPres.groupTemplate ?? ''
|
||||
db.seperateParametersEnabled = newPres.seperateParametersEnabled ?? false
|
||||
db.seperateParameters = newPres.seperateParameters ? safeStructuredClone(newPres.seperateParameters) : {
|
||||
memory: {},
|
||||
emotion: {},
|
||||
translate: {},
|
||||
otherAx: {}
|
||||
}
|
||||
db.OAIPrediction = newPres.openAIPrediction ?? ''
|
||||
db.customAPIFormat = safeStructuredClone(newPres.customAPIFormat) ?? LLMFormat.OpenAICompatible
|
||||
db.systemContentReplacement = newPres.systemContentReplacement ?? ''
|
||||
db.systemRoleReplacement = newPres.systemRoleReplacement ?? 'user'
|
||||
return db
|
||||
}
|
||||
|
||||
@@ -1402,11 +1583,14 @@ import type { OnnxModelFiles } from '../process/transformers';
|
||||
import type { RisuModule } from '../process/modules';
|
||||
import type { HypaV2Data } from '../process/memory/hypav2';
|
||||
import { decodeRPack, encodeRPack } from '../rpack/rpack_bg';
|
||||
import { DBState, selectedCharID } from '../stores.svelte';
|
||||
import { LLMFormat } from '../model/modellist';
|
||||
import type { Parameter } from '../process/request';
|
||||
|
||||
export async function downloadPreset(id:number, type:'json'|'risupreset'|'return' = 'json'){
|
||||
saveCurrentPreset()
|
||||
let db = get(DataBase)
|
||||
let pres = structuredClone(db.botPresets[id])
|
||||
let db = getDatabase()
|
||||
let pres = safeStructuredClone(db.botPresets[id])
|
||||
console.log(pres)
|
||||
pres.openAIKey = ''
|
||||
pres.forceReplaceUrl = ''
|
||||
@@ -1476,10 +1660,10 @@ export async function importPreset(f:{
|
||||
pre = {...presetTemplate,...(JSON.parse(Buffer.from(f.data).toString('utf-8')))}
|
||||
console.log(pre)
|
||||
}
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(pre.presetVersion && pre.presetVersion >= 3){
|
||||
//NAI preset
|
||||
const pr = structuredClone(prebuiltPresets.NAI2)
|
||||
const pr = safeStructuredClone(prebuiltPresets.NAI2)
|
||||
pr.temperature = pre.parameters.temperature * 100
|
||||
pr.maxResponse = pre.parameters.max_length
|
||||
pr.NAISettings.topK = pre.parameters.top_k
|
||||
@@ -1504,7 +1688,7 @@ export async function importPreset(f:{
|
||||
|
||||
if(Array.isArray(pre?.prompt_order?.[0]?.order) && Array.isArray(pre?.prompts)){
|
||||
//ST preset
|
||||
const pr = structuredClone(presetTemplate)
|
||||
const pr = safeStructuredClone(presetTemplate)
|
||||
pr.promptTemplate = []
|
||||
|
||||
function findPrompt(identifier:number){
|
||||
@@ -1,11 +1,11 @@
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase } from "./database";
|
||||
import { downloadFile } from "./globalApi";
|
||||
import { getDatabase } from "./database.svelte";
|
||||
import { downloadFile } from "../globalApi.svelte";
|
||||
import { alertNormal } from "../alert";
|
||||
import { language } from "src/lang";
|
||||
|
||||
export async function exportAsDataset(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
|
||||
let dataset = []
|
||||
for(const char of db.characters){
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { get } from "svelte/store";
|
||||
import { DataBase } from "./database";
|
||||
import { getDatabase } from "./database.svelte";
|
||||
import { alertNormal } from "../alert";
|
||||
import { language } from "src/lang";
|
||||
import { isNodeServer, isTauri } from "./globalApi";
|
||||
import { isNodeServer, isTauri } from "../globalApi.svelte";
|
||||
|
||||
async function requestPersistantStorageMain() {
|
||||
|
||||
@@ -38,7 +38,7 @@ async function requestPersistantStorageMain() {
|
||||
}
|
||||
|
||||
export async function persistantStorageRecommended() {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(navigator.storage && navigator.storage.persist && (!isTauri) && (!isNodeServer)) {
|
||||
if(await navigator.storage.persisted()) {
|
||||
return false;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Packr, Unpackr, decode } from "msgpackr";
|
||||
import * as fflate from "fflate";
|
||||
import { isTauri } from "./globalApi";
|
||||
import { AppendableBuffer, isTauri } from "../globalApi.svelte";
|
||||
|
||||
const packr = new Packr({
|
||||
useRecords:false
|
||||
@@ -12,9 +12,22 @@ const unpackr = new Unpackr({
|
||||
})
|
||||
|
||||
const magicHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 7]);
|
||||
const magicCompressedHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 8]);
|
||||
const magicCompressedHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 8]);
|
||||
const magicStreamCompressedHeader = new Uint8Array([0, 82, 73, 83, 85, 83, 65, 86, 69, 0, 9]);
|
||||
|
||||
export function encodeRisuSave(data:any, compression:'noCompression'|'compression' = 'noCompression'){
|
||||
|
||||
async function checkCompressionStreams(){
|
||||
if(!CompressionStream){
|
||||
const {makeCompressionStream} = await import('compression-streams-polyfill/ponyfill');
|
||||
globalThis.CompressionStream = makeCompressionStream(TransformStream);
|
||||
}
|
||||
if(!DecompressionStream){
|
||||
const {makeDecompressionStream} = await import('compression-streams-polyfill/ponyfill');
|
||||
globalThis.DecompressionStream = makeDecompressionStream(TransformStream);
|
||||
}
|
||||
}
|
||||
|
||||
export function encodeRisuSaveLegacy(data:any, compression:'noCompression'|'compression' = 'noCompression'){
|
||||
let encoded:Uint8Array = packr.encode(data)
|
||||
if(compression === 'compression'){
|
||||
encoded = fflate.compressSync(encoded)
|
||||
@@ -31,7 +44,21 @@ export function encodeRisuSave(data:any, compression:'noCompression'|'compressio
|
||||
}
|
||||
}
|
||||
|
||||
export function decodeRisuSave(data:Uint8Array){
|
||||
export async function encodeRisuSave(data:any) {
|
||||
await checkCompressionStreams()
|
||||
let encoded:Uint8Array = packr.encode(data)
|
||||
const cs = new CompressionStream('gzip');
|
||||
const writer = cs.writable.getWriter();
|
||||
writer.write(encoded);
|
||||
writer.close();
|
||||
const buf = await new Response(cs.readable).arrayBuffer()
|
||||
const result = new Uint8Array(new Uint8Array(buf).length + magicStreamCompressedHeader.length);
|
||||
result.set(magicStreamCompressedHeader, 0)
|
||||
result.set(new Uint8Array(buf), magicStreamCompressedHeader.length)
|
||||
return result
|
||||
}
|
||||
|
||||
export async function decodeRisuSave(data:Uint8Array){
|
||||
try {
|
||||
switch(checkHeader(data)){
|
||||
case "compressed":
|
||||
@@ -40,6 +67,16 @@ export function decodeRisuSave(data:Uint8Array){
|
||||
case "raw":
|
||||
data = data.slice(magicHeader.length)
|
||||
return unpackr.decode(data)
|
||||
case "stream":{
|
||||
await checkCompressionStreams()
|
||||
data = data.slice(magicStreamCompressedHeader.length)
|
||||
const cs = new DecompressionStream('gzip');
|
||||
const writer = cs.writable.getWriter();
|
||||
writer.write(data);
|
||||
writer.close();
|
||||
const buf = await new Response(cs.readable).arrayBuffer()
|
||||
return unpackr.decode(new Uint8Array(buf))
|
||||
}
|
||||
}
|
||||
return unpackr.decode(data)
|
||||
}
|
||||
@@ -63,7 +100,7 @@ export function decodeRisuSave(data:Uint8Array){
|
||||
|
||||
function checkHeader(data: Uint8Array) {
|
||||
|
||||
let header:'none'|'compressed'|'raw' = 'raw'
|
||||
let header:'none'|'compressed'|'raw'|'stream' = 'raw'
|
||||
|
||||
if (data.length < magicHeader.length) {
|
||||
return false;
|
||||
@@ -84,7 +121,18 @@ function checkHeader(data: Uint8Array) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(header === 'none'){
|
||||
header = 'stream'
|
||||
for (let i = 0; i < magicStreamCompressedHeader.length; i++) {
|
||||
if (data[i] !== magicStreamCompressedHeader[i]) {
|
||||
header = 'none'
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All bytes matched
|
||||
return header;
|
||||
}
|
||||
117
src/ts/stores.svelte.ts
Normal file
117
src/ts/stores.svelte.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import type { character, Database, groupChat } from "./storage/database.svelte";
|
||||
import type { simpleCharacterArgument } from "./parser.svelte";
|
||||
import type { alertData } from "./alert";
|
||||
import { getModules, moduleUpdate } from "./process/modules";
|
||||
import { resetScriptCache } from "./process/scripts";
|
||||
|
||||
function updateSize(){
|
||||
SizeStore.set({
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight
|
||||
})
|
||||
DynamicGUI.set(window.innerWidth <= 1024)
|
||||
}
|
||||
|
||||
export const SizeStore = writable({
|
||||
w: 0,
|
||||
h: 0
|
||||
})
|
||||
|
||||
const t = 'https://raw.githubusercontent.com/ProjectAliceDev/ProjectAliceDev.github.io/master/'
|
||||
export const loadedStore = writable(false)
|
||||
export const DynamicGUI = writable(false)
|
||||
export const sideBarClosing = writable(false)
|
||||
export const sideBarStore = writable(window.innerWidth > 1024)
|
||||
export const selectedCharID = writable(-1)
|
||||
export const CharEmotion = writable({} as {[key:string]: [string, string, number][]})
|
||||
export const ViewBoxsize = writable({ width: 12 * 16, height: 12 * 16 }); // Default width and height in pixels
|
||||
export const settingsOpen = writable(false)
|
||||
export const botMakerMode = writable(false)
|
||||
export const moduleBackgroundEmbedding = writable('')
|
||||
export const openPresetList = writable(false)
|
||||
export const openPersonaList = writable(false)
|
||||
export const MobileGUI = writable(false)
|
||||
export const MobileGUIStack = writable(0)
|
||||
export const MobileSideBar = writable(0)
|
||||
export const ShowVN = writable(false)
|
||||
export const SettingsMenuIndex = writable(-1)
|
||||
export const ReloadGUIPointer = writable(0)
|
||||
export const OpenRealmStore = writable(false)
|
||||
export const ShowRealmFrameStore = writable('')
|
||||
export const PlaygroundStore = writable(0)
|
||||
export const HideIconStore = writable(false)
|
||||
export const CustomCSSStore = writable('')
|
||||
export const SafeModeStore = writable(false)
|
||||
export const MobileSearch = writable('')
|
||||
export const CharConfigSubMenu = writable(0)
|
||||
export const CustomGUISettingMenuStore = writable(false)
|
||||
export const alertStore = writable({
|
||||
type: 'none',
|
||||
msg: 'n',
|
||||
} as alertData)
|
||||
export const selIdState = $state({
|
||||
selId: -1
|
||||
})
|
||||
|
||||
|
||||
CustomCSSStore.subscribe((css) => {
|
||||
console.log(css)
|
||||
const q = document.querySelector('#customcss')
|
||||
if(q){
|
||||
q.innerHTML = css
|
||||
}
|
||||
else{
|
||||
const s = document.createElement('style')
|
||||
s.id = 'customcss'
|
||||
s.innerHTML = css
|
||||
document.body.appendChild(s)
|
||||
}
|
||||
})
|
||||
|
||||
export function createSimpleCharacter(char:character|groupChat){
|
||||
if((!char) || char.type === 'group'){
|
||||
return null
|
||||
}
|
||||
|
||||
const simpleChar:simpleCharacterArgument = {
|
||||
type: "simple",
|
||||
customscript: char.customscript,
|
||||
chaId: char.chaId,
|
||||
additionalAssets: char.additionalAssets,
|
||||
virtualscript: char.virtualscript,
|
||||
emotionImages: char.emotionImages,
|
||||
triggerscript: char.triggerscript,
|
||||
}
|
||||
|
||||
return simpleChar
|
||||
|
||||
}
|
||||
|
||||
updateSize()
|
||||
window.addEventListener("resize", updateSize);
|
||||
export const DBState = $state({
|
||||
db: {} as any as Database
|
||||
});
|
||||
|
||||
export const disableHighlight = writable(true)
|
||||
|
||||
ReloadGUIPointer.subscribe(() => {
|
||||
resetScriptCache()
|
||||
})
|
||||
|
||||
$effect.root(() => {
|
||||
selectedCharID.subscribe((v) => {
|
||||
selIdState.selId = v
|
||||
})
|
||||
$effect(() => {
|
||||
$state.snapshot(DBState.db.modules)
|
||||
DBState?.db?.enabledModules
|
||||
DBState?.db?.enabledModules?.length
|
||||
DBState?.db?.characters?.[selIdState.selId]?.chats?.[DBState?.db?.characters?.[selIdState.selId]?.chatPage]?.modules?.length
|
||||
DBState?.db?.characters?.[selIdState.selId]?.hideChatIcon
|
||||
DBState?.db?.characters?.[selIdState.selId]?.backgroundHTML
|
||||
DBState?.db?.moduleIntergration
|
||||
moduleUpdate()
|
||||
})
|
||||
})
|
||||
269
src/ts/stores.ts
269
src/ts/stores.ts
@@ -1,269 +0,0 @@
|
||||
import { get, writable, type Writable } from "svelte/store";
|
||||
import { DataBase, type Chat, type character, type groupChat } from "./storage/database";
|
||||
import { isEqual } from "lodash";
|
||||
import type { simpleCharacterArgument } from "./parser";
|
||||
import { getUserIcon, getUserIconProtrait, getUserName, sleep } from "./util";
|
||||
import { getModules } from "./process/modules";
|
||||
|
||||
function updateSize(){
|
||||
SizeStore.set({
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight
|
||||
})
|
||||
DynamicGUI.set(window.innerWidth <= 1024)
|
||||
}
|
||||
|
||||
export const SizeStore = writable({
|
||||
w: 0,
|
||||
h: 0
|
||||
})
|
||||
export const DynamicGUI = writable(false)
|
||||
export const sideBarClosing = writable(false)
|
||||
export const sideBarStore = writable(window.innerWidth > 1024)
|
||||
export const selectedCharID = writable(-1)
|
||||
export const CharEmotion = writable({} as {[key:string]: [string, string, number][]})
|
||||
export const ViewBoxsize = writable({ width: 12 * 16, height: 12 * 16 }); // Default width and height in pixels
|
||||
export const settingsOpen = writable(false)
|
||||
export const botMakerMode = writable(false)
|
||||
export const moduleBackgroundEmbedding = writable('')
|
||||
export const openPresetList = writable(false)
|
||||
export const openPersonaList = writable(false)
|
||||
export const MobileGUI = writable(false)
|
||||
export const MobileGUIStack = writable(0)
|
||||
export const MobileSideBar = writable(0)
|
||||
//optimization
|
||||
export const CurrentCharacter = writable(null) as Writable<character | groupChat>
|
||||
export const CurrentSimpleCharacter = writable(null) as Writable<simpleCharacterArgument>
|
||||
export const CurrentChat = writable(null) as Writable<Chat>
|
||||
export const CurrentUsername = writable('') as Writable<string>
|
||||
export const CurrentUserIcon = writable('') as Writable<string>
|
||||
export const CurrentShowMemoryLimit = writable(false) as Writable<boolean>
|
||||
export const ShowVN = writable(false)
|
||||
export const SettingsMenuIndex = writable(-1)
|
||||
export const ReloadGUIPointer = writable(0)
|
||||
export const OpenRealmStore = writable(false)
|
||||
export const ShowRealmFrameStore = writable('')
|
||||
export const PlaygroundStore = writable(0)
|
||||
export const HideIconStore = writable(false)
|
||||
export const UserIconProtrait = writable(false)
|
||||
export const CustomCSSStore = writable('')
|
||||
export const SafeModeStore = writable(false)
|
||||
export const MobileSearch = writable('')
|
||||
export const CharConfigSubMenu = writable(0)
|
||||
|
||||
let lastGlobalEnabledModules: string[] = []
|
||||
let lastChatEnabledModules: string[] = []
|
||||
let moduleHideIcon = false
|
||||
let characterHideIcon = false
|
||||
|
||||
|
||||
CustomCSSStore.subscribe((css) => {
|
||||
console.log(css)
|
||||
const q = document.querySelector('#customcss')
|
||||
if(q){
|
||||
q.innerHTML = css
|
||||
}
|
||||
else{
|
||||
const s = document.createElement('style')
|
||||
s.id = 'customcss'
|
||||
s.innerHTML = css
|
||||
document.body.appendChild(s)
|
||||
}
|
||||
})
|
||||
|
||||
function createSimpleCharacter(char:character|groupChat){
|
||||
if((!char) || char.type === 'group'){
|
||||
return null
|
||||
}
|
||||
|
||||
const simpleChar:simpleCharacterArgument = {
|
||||
type: "simple",
|
||||
customscript: structuredClone(char.customscript),
|
||||
chaId: char.chaId,
|
||||
additionalAssets: char.additionalAssets,
|
||||
virtualscript: char.virtualscript,
|
||||
emotionImages: char.emotionImages,
|
||||
triggerscript: char.triggerscript,
|
||||
}
|
||||
|
||||
return simpleChar
|
||||
|
||||
}
|
||||
|
||||
function trySync(){
|
||||
try {
|
||||
let db = get(DataBase)
|
||||
let currentChar = get(selectedCharID)
|
||||
let currentCharacter = db.characters ? (db.characters[currentChar]) : null
|
||||
let currentChat = currentCharacter ? (currentCharacter.chats[currentCharacter.chatPage]) : null
|
||||
CurrentCharacter.set(structuredClone(currentCharacter))
|
||||
CurrentSimpleCharacter.set(createSimpleCharacter(currentCharacter))
|
||||
CurrentChat.set(structuredClone(currentChat))
|
||||
CurrentUsername.set(getUserName())
|
||||
CurrentUserIcon.set(getUserIcon())
|
||||
CurrentShowMemoryLimit.set(db.showMemoryLimit)
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
trySync()
|
||||
|
||||
async function preInit(){
|
||||
await sleep(1)
|
||||
trySync()
|
||||
function updateCurrentCharacter(){
|
||||
|
||||
const db = get(DataBase)
|
||||
if(!db.characters){
|
||||
CurrentCharacter.set(null)
|
||||
updateCurrentChat()
|
||||
return
|
||||
}
|
||||
|
||||
const currentCharId = get(selectedCharID)
|
||||
const currentChar = db.characters[currentCharId]
|
||||
const gotCharacter = get(CurrentCharacter)
|
||||
if(isEqual(gotCharacter, currentChar)){
|
||||
return
|
||||
}
|
||||
if((currentChar?.viewScreen === 'vn') !== get(ShowVN)){
|
||||
ShowVN.set(currentChar?.viewScreen === 'vn')
|
||||
}
|
||||
|
||||
CurrentCharacter.set(structuredClone(currentChar))
|
||||
const simp = createSimpleCharacter(currentChar)
|
||||
|
||||
if(!isEqual(get(CurrentSimpleCharacter), simp)){
|
||||
CurrentSimpleCharacter.set(simp)
|
||||
}
|
||||
|
||||
updateCurrentChat()
|
||||
}
|
||||
|
||||
function updateCurrentChat(){
|
||||
const currentChar = get(CurrentCharacter)
|
||||
if(!currentChar){
|
||||
CurrentChat.set(null)
|
||||
return
|
||||
}
|
||||
const chat = (currentChar.chats[currentChar.chatPage])
|
||||
const gotChat = get(CurrentChat)
|
||||
if(isEqual(gotChat, chat)){
|
||||
return
|
||||
}
|
||||
CurrentChat.set(structuredClone(chat))
|
||||
}
|
||||
|
||||
DataBase.subscribe((data) => {
|
||||
updateCurrentCharacter()
|
||||
if(getUserName() !== get(CurrentUsername)){
|
||||
CurrentUsername.set(getUserName())
|
||||
}
|
||||
if(getUserIcon() !== get(CurrentUserIcon)){
|
||||
CurrentUserIcon.set(getUserIcon())
|
||||
}
|
||||
if(getUserIconProtrait() !== get(UserIconProtrait)){
|
||||
UserIconProtrait.set(getUserIconProtrait())
|
||||
}
|
||||
if(data.showMemoryLimit !== get(CurrentShowMemoryLimit)){
|
||||
CurrentShowMemoryLimit.set(data.showMemoryLimit)
|
||||
}
|
||||
if(!isEqual(data.enabledModules, lastGlobalEnabledModules)){
|
||||
lastGlobalEnabledModules = data.enabledModules || []
|
||||
onModuleUpdate()
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
selectedCharID.subscribe((id) => {
|
||||
|
||||
updateCurrentCharacter()
|
||||
})
|
||||
|
||||
CurrentCharacter.subscribe((char) => {
|
||||
updateCurrentChat()
|
||||
let db = get(DataBase)
|
||||
let charId = get(selectedCharID)
|
||||
if(char?.hideChatIcon !== characterHideIcon){
|
||||
characterHideIcon = char?.hideChatIcon
|
||||
HideIconStore.set(characterHideIcon || moduleHideIcon)
|
||||
}
|
||||
if(getUserName() !== get(CurrentUsername)){
|
||||
CurrentUsername.set(getUserName())
|
||||
}
|
||||
if(getUserIcon() !== get(CurrentUserIcon)){
|
||||
CurrentUserIcon.set(getUserIcon())
|
||||
}
|
||||
if(getUserIconProtrait() !== get(UserIconProtrait)){
|
||||
UserIconProtrait.set(getUserIconProtrait())
|
||||
}
|
||||
if(charId === -1 || charId > db.characters.length){
|
||||
return
|
||||
}
|
||||
let cha = db.characters[charId]
|
||||
if(isEqual(cha, char)){
|
||||
return
|
||||
}
|
||||
db.characters[charId] = structuredClone(char)
|
||||
DataBase.set(db)
|
||||
})
|
||||
|
||||
CurrentChat.subscribe((chat) => {
|
||||
let currentChar = get(CurrentCharacter)
|
||||
|
||||
if(currentChar){
|
||||
if(!isEqual(currentChar.chats[currentChar.chatPage], chat)){
|
||||
currentChar.chats[currentChar.chatPage] = structuredClone(chat)
|
||||
CurrentCharacter.set(currentChar)
|
||||
}
|
||||
}
|
||||
|
||||
if(!isEqual(lastChatEnabledModules, chat?.modules)){
|
||||
lastChatEnabledModules = chat?.modules || []
|
||||
onModuleUpdate()
|
||||
return
|
||||
}
|
||||
|
||||
if(getUserName() !== get(CurrentUsername)){
|
||||
CurrentUsername.set(getUserName())
|
||||
}
|
||||
|
||||
if(getUserIcon() !== get(CurrentUserIcon)){
|
||||
CurrentUserIcon.set(getUserIcon())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function onModuleUpdate(){
|
||||
if(!Array.isArray(lastGlobalEnabledModules)){
|
||||
lastGlobalEnabledModules = []
|
||||
}
|
||||
if(!Array.isArray(lastChatEnabledModules)){
|
||||
lastChatEnabledModules = []
|
||||
}
|
||||
|
||||
const m = getModules()
|
||||
|
||||
let moduleHideIcon = false
|
||||
let backgroundEmbedding = ''
|
||||
m.forEach((module) => {
|
||||
if(!module){
|
||||
return
|
||||
}
|
||||
|
||||
if(module.hideIcon){
|
||||
moduleHideIcon = true
|
||||
}
|
||||
if(module.backgroundEmbedding){
|
||||
backgroundEmbedding += '\n' + module.backgroundEmbedding + '\n'
|
||||
}
|
||||
})
|
||||
|
||||
if(backgroundEmbedding){
|
||||
moduleBackgroundEmbedding.set(backgroundEmbedding)
|
||||
}
|
||||
HideIconStore.set(characterHideIcon || moduleHideIcon)
|
||||
}
|
||||
|
||||
updateSize()
|
||||
window.addEventListener("resize", updateSize);
|
||||
preInit()
|
||||
@@ -1,12 +1,12 @@
|
||||
import { v4 } from 'uuid';
|
||||
import { alertError, alertInput, alertNormal, alertStore, alertWait } from '../alert';
|
||||
import { get, writable } from 'svelte/store';
|
||||
import { DataBase, setDatabase, type character, saveImage, type Chat } from '../storage/database';
|
||||
import { CurrentChat, selectedCharID } from '../stores';
|
||||
import { setDatabase, type character, saveImage, type Chat, getCurrentChat, setCurrentChat, getDatabase } from '../storage/database.svelte';
|
||||
import { selectedCharID } from '../stores.svelte';
|
||||
import { findCharacterIndexbyId, sleep } from '../util';
|
||||
import type { DataConnection, Peer } from 'peerjs';
|
||||
import { readImage } from '../storage/globalApi';
|
||||
import { doingChat } from '../process';
|
||||
import { readImage } from '../globalApi.svelte';
|
||||
import { doingChat } from '../process/index.svelte';
|
||||
|
||||
async function importPeerJS(){
|
||||
return await import('peerjs');
|
||||
@@ -79,9 +79,11 @@ export async function createMultiuserRoom(){
|
||||
console.log("new connection", conn)
|
||||
|
||||
async function requestChar(excludeAssets:string[]|null = null){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase({
|
||||
snapshot: true
|
||||
})
|
||||
const selectedCharId = get(selectedCharID)
|
||||
const char = structuredClone(db.characters[selectedCharId])
|
||||
const char = safeStructuredClone(db.characters[selectedCharId])
|
||||
if(char.type === 'group'){
|
||||
return
|
||||
}
|
||||
@@ -127,9 +129,11 @@ export async function createMultiuserRoom(){
|
||||
requestChar()
|
||||
}
|
||||
if(data.type === 'receive-char'){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase({
|
||||
snapshot: true
|
||||
})
|
||||
const selectedCharId = get(selectedCharID)
|
||||
const char = structuredClone(db.characters[selectedCharId])
|
||||
const char = safeStructuredClone(db.characters[selectedCharId])
|
||||
const recivedChar = data.data
|
||||
if(char.type === 'group'){
|
||||
return
|
||||
@@ -137,7 +141,7 @@ export async function createMultiuserRoom(){
|
||||
char.chats[char.chatPage] = recivedChar.chats[0]
|
||||
}
|
||||
if(data.type === 'request-chat-sync'){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedCharId = get(selectedCharID)
|
||||
const char = db.characters[selectedCharId]
|
||||
char.chats[char.chatPage] = data.data
|
||||
@@ -157,7 +161,7 @@ export async function createMultiuserRoom(){
|
||||
}
|
||||
}
|
||||
if(data.type === 'request-chat'){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const selectedCharId = get(selectedCharID)
|
||||
const char = db.characters[selectedCharId]
|
||||
const chat = char.chats[char.chatPage]
|
||||
@@ -285,7 +289,7 @@ export async function joinMultiuserRoom(){
|
||||
switch(data.type){
|
||||
case 'receive-char':{
|
||||
//create temp character
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const cha = data.data
|
||||
cha.chaId = '§temp'
|
||||
cha.chatPage = 0
|
||||
@@ -309,9 +313,11 @@ export async function joinMultiuserRoom(){
|
||||
break
|
||||
}
|
||||
case 'receive-chat':{
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase({
|
||||
snapshot: true
|
||||
})
|
||||
const selectedCharId = get(selectedCharID)
|
||||
const char = structuredClone(db.characters[selectedCharId])
|
||||
const char = safeStructuredClone(db.characters[selectedCharId])
|
||||
char.chats[char.chatPage] = data.data
|
||||
db.characters[selectedCharId] = char
|
||||
latestSyncChat = data.data
|
||||
@@ -365,7 +371,7 @@ export async function peerSync(){
|
||||
return
|
||||
}
|
||||
await sleep(1)
|
||||
const chat = get(CurrentChat)
|
||||
const chat = getCurrentChat()
|
||||
latestSyncChat = chat
|
||||
if(!conn){
|
||||
// host user
|
||||
@@ -426,5 +432,5 @@ export function peerRevertChat() {
|
||||
if(!connectionOpen || !latestSyncChat){
|
||||
return
|
||||
}
|
||||
CurrentChat.set(latestSyncChat)
|
||||
setCurrentChat(latestSyncChat)
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
import type { Tiktoken } from "@dqbd/tiktoken";
|
||||
import type { Tokenizer } from "@mlc-ai/web-tokenizers";
|
||||
import { DataBase, type groupChat, type character, type Chat } from "./storage/database";
|
||||
import { get } from "svelte/store";
|
||||
import type { MultiModal, OpenAIChat } from "./process";
|
||||
import { type groupChat, type character, type Chat, getCurrentCharacter, getDatabase } from "./storage/database.svelte";
|
||||
import type { MultiModal, OpenAIChat } from "./process/index.svelte";
|
||||
import { supportsInlayImage } from "./process/files/image";
|
||||
import { risuChatParser } from "./parser";
|
||||
import { risuChatParser } from "./parser.svelte";
|
||||
import { tokenizeGGUFModel } from "./process/models/local";
|
||||
import { globalFetch } from "./storage/globalApi";
|
||||
import { CurrentCharacter } from "./stores";
|
||||
import { globalFetch } from "./globalApi.svelte";
|
||||
|
||||
|
||||
export const tokenizerList = [
|
||||
@@ -23,7 +21,7 @@ export const tokenizerList = [
|
||||
] as const
|
||||
|
||||
export async function encode(data:string):Promise<(number[]|Uint32Array|Int32Array)>{
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(db.aiModel === 'openrouter' || db.aiModel === 'reverse_proxy'){
|
||||
switch(db.customTokenizer){
|
||||
case 'mistral':
|
||||
@@ -43,12 +41,7 @@ export async function encode(data:string):Promise<(number[]|Uint32Array|Int32Arr
|
||||
case 'cohere':
|
||||
return await tokenizeWebTokenizers(data, 'cohere')
|
||||
default:
|
||||
// Add exception for gpt-4o tokenizers on reverse_proxy
|
||||
if(db.proxyRequestModel?.startsWith('gpt4o') ||
|
||||
(db.proxyRequestModel === 'custom' && db.customProxyRequestModel.startsWith('gpt-4o'))) {
|
||||
return await tikJS(data, 'o200k_base')
|
||||
}
|
||||
return await tikJS(data)
|
||||
return await tikJS(data, 'o200k_base')
|
||||
}
|
||||
}
|
||||
if(db.aiModel.startsWith('novellist')){
|
||||
@@ -131,7 +124,7 @@ async function tikJS(text:string, model='cl100k_base') {
|
||||
}
|
||||
|
||||
async function geminiTokenizer(text:string) {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const fetchResult = await globalFetch(`https://generativelanguage.googleapis.com/v1beta/${db.aiModel}:countTextTokens`, {
|
||||
"headers": {
|
||||
"content-type": "application/json",
|
||||
@@ -250,7 +243,7 @@ export class ChatTokenizer {
|
||||
}
|
||||
|
||||
async tokenizeMultiModal(data:MultiModal){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
if(!supportsInlayImage()){
|
||||
return this.chatAdditonalTokens
|
||||
}
|
||||
@@ -353,7 +346,7 @@ export async function getCharToken(char?:character|groupChat|null){
|
||||
let dynamic = 0
|
||||
|
||||
if(!char){
|
||||
const c = get(CurrentCharacter)
|
||||
const c = getCurrentCharacter()
|
||||
char = c
|
||||
}
|
||||
if(char.type === 'group'){
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
import { get } from "svelte/store"
|
||||
import { translatorPlugin } from "../plugins/plugins"
|
||||
import { DataBase, type character, type customscript, type groupChat } from "../storage/database"
|
||||
import { globalFetch, isTauri } from "../storage/globalApi"
|
||||
import { getDatabase, type character, type customscript, type groupChat } from "../storage/database.svelte"
|
||||
import { globalFetch, isTauri } from "../globalApi.svelte"
|
||||
import { alertError } from "../alert"
|
||||
import { requestChatData } from "../process/request"
|
||||
import { doingChat, type OpenAIChat } from "../process"
|
||||
import { applyMarkdownToNode, parseChatML, type simpleCharacterArgument } from "../parser"
|
||||
import { selectedCharID } from "../stores"
|
||||
import { doingChat, type OpenAIChat } from "../process/index.svelte"
|
||||
import { applyMarkdownToNode, parseChatML, type simpleCharacterArgument } from "../parser.svelte"
|
||||
import { selectedCharID } from "../stores.svelte"
|
||||
import { getModuleRegexScripts } from "../process/modules"
|
||||
import { getNodetextToSentence, sleep } from "../util"
|
||||
import { processScriptFull } from "../process/scripts"
|
||||
import { Capacitor } from "@capacitor/core"
|
||||
import localforage from "localforage"
|
||||
|
||||
let cache={
|
||||
origin: [''],
|
||||
trans: ['']
|
||||
}
|
||||
|
||||
const LLMCacheStorage = localforage.createInstance({
|
||||
name: "LLMTranslateCache"
|
||||
})
|
||||
|
||||
let waitTrans = 0
|
||||
|
||||
export async function translate(text:string, reverse:boolean) {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const plug = await translatorPlugin(text, reverse ? db.translator: 'en', reverse ? 'en' : db.translator)
|
||||
if(plug){
|
||||
return plug.content
|
||||
@@ -105,7 +109,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 = get(DataBase)
|
||||
let db = getDatabase()
|
||||
if(db.translatorType === 'llm'){
|
||||
const tr = db.translator || 'en'
|
||||
return translateLLM(text, {to: tr})
|
||||
@@ -208,15 +212,15 @@ async function jaTrans(text:string) {
|
||||
}
|
||||
|
||||
export function isExpTranslator(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
return db.translatorType === 'llm' || db.translatorType === 'deepl' || db.translatorType === 'deeplX'
|
||||
}
|
||||
|
||||
export async function translateHTML(html: string, reverse:boolean, charArg:simpleCharacterArgument|string = '', chatID:number): Promise<string> {
|
||||
export async function translateHTML(html: string, reverse:boolean, charArg:simpleCharacterArgument|string = '', chatID:number, regenerate = false): Promise<string> {
|
||||
let alwaysExistChar: character | groupChat | simpleCharacterArgument;
|
||||
if(charArg !== ''){
|
||||
if(typeof(charArg) === 'string'){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const charId = get(selectedCharID)
|
||||
alwaysExistChar = db.characters[charId]
|
||||
}
|
||||
@@ -232,7 +236,7 @@ export async function translateHTML(html: string, reverse:boolean, charArg:simpl
|
||||
chaId: 'simple'
|
||||
}
|
||||
}
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let DoingChat = get(doingChat)
|
||||
if(DoingChat){
|
||||
if(isExpTranslator()){
|
||||
@@ -241,7 +245,7 @@ export async function translateHTML(html: string, reverse:boolean, charArg:simpl
|
||||
}
|
||||
if(db.translatorType === 'llm'){
|
||||
const tr = db.translator || 'en'
|
||||
return translateLLM(html, {to: tr})
|
||||
return translateLLM(html, {to: tr, regenerate})
|
||||
}
|
||||
const dom = new DOMParser().parseFromString(html, 'text/html');
|
||||
console.log(html)
|
||||
@@ -440,13 +444,15 @@ export async function translateHTML(html: string, reverse:boolean, charArg:simpl
|
||||
}
|
||||
|
||||
function needSuperChunkedTranslate(){
|
||||
return get(DataBase).translatorType === 'deeplX'
|
||||
return getDatabase().translatorType === 'deeplX'
|
||||
}
|
||||
|
||||
let llmCache = new Map<string, string>()
|
||||
async function translateLLM(text:string, arg:{to:string}){
|
||||
if(llmCache.has(text)){
|
||||
return llmCache.get(text)
|
||||
async function translateLLM(text:string, arg:{to:string, regenerate?:boolean}):Promise<string>{
|
||||
if(!arg.regenerate){
|
||||
const cacheMatch = await LLMCacheStorage.getItem(text)
|
||||
if(cacheMatch){
|
||||
return cacheMatch as string
|
||||
}
|
||||
}
|
||||
const styleDecodeRegex = /\<risu-style\>(.+?)\<\/risu-style\>/gms
|
||||
let styleDecodes:string[] = []
|
||||
@@ -455,15 +461,24 @@ async function translateLLM(text:string, arg:{to:string}){
|
||||
return `<style-data style-index="${styleDecodes.length-1}"></style-data>`
|
||||
})
|
||||
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const charIndex = get(selectedCharID)
|
||||
const currentChar = db.characters[charIndex]
|
||||
let translatorNote
|
||||
if (currentChar.type === "character") {
|
||||
translatorNote = currentChar.translatorNote ?? ""
|
||||
} else {
|
||||
translatorNote = ""
|
||||
}
|
||||
|
||||
let formated:OpenAIChat[] = []
|
||||
let prompt = db.translatorPrompt || `You are a translator. translate the following html or text into {{slot}}. do not output anything other than the translation.`
|
||||
let parsedPrompt = parseChatML(prompt.replaceAll('{{slot}}', arg.to).replaceAll('{{solt::content}}', text))
|
||||
let parsedPrompt = parseChatML(prompt.replaceAll('{{slot}}', arg.to).replaceAll('{{solt::content}}', text).replaceAll('{{slot::tnote}}', translatorNote))
|
||||
if(parsedPrompt){
|
||||
formated = parsedPrompt
|
||||
}
|
||||
else{
|
||||
prompt = prompt.replaceAll('{{slot}}', arg.to)
|
||||
prompt = prompt.replaceAll('{{slot}}', arg.to).replaceAll('{{slot::tnote}}', translatorNote)
|
||||
formated = [
|
||||
{
|
||||
'role': 'system',
|
||||
@@ -481,7 +496,7 @@ async function translateLLM(text:string, arg:{to:string}){
|
||||
useStreaming: false,
|
||||
noMultiGen: true,
|
||||
maxTokens: db.translatorMaxResponse,
|
||||
}, 'submodel')
|
||||
}, 'translate')
|
||||
|
||||
if(rq.type === 'fail' || rq.type === 'streaming' || rq.type === 'multiline'){
|
||||
alertError(`${rq.result}`)
|
||||
@@ -490,6 +505,10 @@ async function translateLLM(text:string, arg:{to:string}){
|
||||
const result = rq.result.replace(/<style-data style-index="(\d+)" ?\/?>/g, (match, p1) => {
|
||||
return styleDecodes[parseInt(p1)] ?? ''
|
||||
}).replace(/<\/style-data>/g, '')
|
||||
llmCache.set(text, result)
|
||||
await LLMCacheStorage.setItem(text, result)
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getLLMCache(text:string):Promise<string | null>{
|
||||
return await LLMCacheStorage.getItem(text)
|
||||
}
|
||||
@@ -2,10 +2,9 @@ import { alertConfirm, alertWait } from "./alert";
|
||||
import { language } from "../lang";
|
||||
import { Capacitor } from "@capacitor/core";
|
||||
import {
|
||||
checkUpdate,
|
||||
installUpdate,
|
||||
} from '@tauri-apps/api/updater'
|
||||
import { relaunch } from '@tauri-apps/api/process'
|
||||
check,
|
||||
} from '@tauri-apps/plugin-updater'
|
||||
import { relaunch } from '@tauri-apps/plugin-process'
|
||||
|
||||
export async function checkRisuUpdate(){
|
||||
|
||||
@@ -14,17 +13,17 @@ export async function checkRisuUpdate(){
|
||||
}
|
||||
|
||||
try {
|
||||
const checked = await checkUpdate()
|
||||
if(checked.shouldUpdate){
|
||||
const checked = await check()
|
||||
if(checked){
|
||||
const conf = await alertConfirm(language.newVersion)
|
||||
if(conf){
|
||||
alertWait(`Updating to ${checked.manifest.version}...`)
|
||||
await installUpdate()
|
||||
alertWait(`Updating to ${checked.version}...`)
|
||||
await checked.downloadAndInstall()
|
||||
await relaunch()
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { get, writable, type Writable } from "svelte/store"
|
||||
import type { Database, Message } from "./storage/database"
|
||||
import { DataBase } from "./storage/database"
|
||||
import { selectedCharID } from "./stores"
|
||||
import {open} from '@tauri-apps/api/dialog'
|
||||
import { readBinaryFile } from "@tauri-apps/api/fs"
|
||||
import type { Database, Message } from "./storage/database.svelte"
|
||||
import { getDatabase } from "./storage/database.svelte"
|
||||
import { selectedCharID } from "./stores.svelte"
|
||||
import {open} from '@tauri-apps/plugin-dialog'
|
||||
import { readFile } from "@tauri-apps/plugin-fs"
|
||||
import { basename } from "@tauri-apps/api/path"
|
||||
import { createBlankChar, getCharImage } from "./characters"
|
||||
import { appWindow } from '@tauri-apps/api/window';
|
||||
import { isTauri } from "./storage/globalApi"
|
||||
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
|
||||
import { isTauri } from "./globalApi.svelte"
|
||||
const appWindow = isTauri ? getCurrentWebviewWindow() : null
|
||||
|
||||
export const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1
|
||||
|
||||
@@ -16,7 +17,7 @@ export interface Messagec extends Message{
|
||||
}
|
||||
|
||||
export function messageForm(arg:Message[], loadPages:number){
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let selectedChar = get(selectedCharID)
|
||||
function reformatContent(data:string){
|
||||
return data.trim()
|
||||
@@ -64,7 +65,7 @@ export async function selectSingleFile(ext:string[]){
|
||||
} else if (selected === null) {
|
||||
return null
|
||||
} else {
|
||||
return {name: await basename(selected),data:await readBinaryFile(selected)}
|
||||
return {name: await basename(selected),data:await readFile(selected)}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,18 +89,18 @@ export async function selectMultipleFile(ext:string[]){
|
||||
if (Array.isArray(selected)) {
|
||||
let arr:{name:string, data:Uint8Array}[] = []
|
||||
for(const file of selected){
|
||||
arr.push({name: await basename(file),data:await readBinaryFile(file)})
|
||||
arr.push({name: await basename(file),data:await readFile(file)})
|
||||
}
|
||||
return arr
|
||||
} else if (selected === null) {
|
||||
return null
|
||||
} else {
|
||||
return [{name: await basename(selected),data:await readBinaryFile(selected)}]
|
||||
return [{name: await basename(selected),data:await readFile(selected)}]
|
||||
}
|
||||
}
|
||||
|
||||
export const replacePlaceholders = (msg:string, name:string) => {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
let selectedChar = get(selectedCharID)
|
||||
let currentChar = db.characters[selectedChar]
|
||||
return msg .replace(/({{char}})|({{Char}})|(<Char>)|(<char>)/gi, currentChar.name)
|
||||
@@ -109,7 +110,7 @@ export const replacePlaceholders = (msg:string, name:string) => {
|
||||
|
||||
function checkPersonaBinded(){
|
||||
try {
|
||||
let db = get(DataBase)
|
||||
let db = getDatabase()
|
||||
const selectedChar = get(selectedCharID)
|
||||
const character = db.characters[selectedChar]
|
||||
const chat = character.chats[character.chatPage]
|
||||
@@ -128,7 +129,7 @@ export function getUserName(){
|
||||
if(bindedPersona){
|
||||
return bindedPersona.name
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
return db.username ?? 'User'
|
||||
}
|
||||
|
||||
@@ -137,7 +138,7 @@ export function getUserIcon(){
|
||||
if(bindedPersona){
|
||||
return bindedPersona.icon
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
return db.userIcon ?? ''
|
||||
}
|
||||
|
||||
@@ -146,7 +147,7 @@ export function getPersonaPrompt(){
|
||||
if(bindedPersona){
|
||||
return bindedPersona.personaPrompt
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
return db.personaPrompt ?? ''
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ export function getUserIconProtrait(){
|
||||
if(bindedPersona){
|
||||
return bindedPersona.largePortrait
|
||||
}
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
return db.personas[db.selectedPersona].largePortrait
|
||||
} catch (error) {
|
||||
return false
|
||||
@@ -171,7 +172,7 @@ export function selectFileByDom(allowedExtensions:string[], multiple:'multiple'|
|
||||
const fileInput = document.createElement('input');
|
||||
fileInput.type = 'file';
|
||||
fileInput.multiple = multiple === 'multiple';
|
||||
const acceptAll = (get(DataBase).allowAllExtentionFiles || checkIsIos() || allowedExtensions[0] === '*')
|
||||
const acceptAll = (getDatabase().allowAllExtentionFiles || checkIsIos() || allowedExtensions[0] === '*')
|
||||
if(!acceptAll){
|
||||
if (allowedExtensions && allowedExtensions.length) {
|
||||
fileInput.accept = allowedExtensions.map(ext => `.${ext}`).join(',');
|
||||
@@ -222,7 +223,7 @@ function readFileAsUint8Array(file) {
|
||||
}
|
||||
|
||||
export async function changeFullscreen(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const isFull = await appWindow.isFullscreen()
|
||||
if(db.fullScreen && (!isFull)){
|
||||
await appWindow.setFullscreen(true)
|
||||
@@ -243,7 +244,7 @@ export async function getCustomBackground(db:string){
|
||||
}
|
||||
|
||||
export function findCharacterbyId(id:string) {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
for(const char of db.characters){
|
||||
if(char.type !== 'group'){
|
||||
if(char.chaId === id){
|
||||
@@ -257,7 +258,7 @@ export function findCharacterbyId(id:string) {
|
||||
}
|
||||
|
||||
export function findCharacterIndexbyId(id:string) {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let i=0;
|
||||
for(const char of db.characters){
|
||||
if(char.chaId === id){
|
||||
@@ -269,7 +270,7 @@ export function findCharacterIndexbyId(id:string) {
|
||||
}
|
||||
|
||||
export function getCharacterIndexObject() {
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
let i=0;
|
||||
let result:{[key:string]:number} = {}
|
||||
for(const char of db.characters){
|
||||
@@ -363,7 +364,7 @@ export async function getEmotion(db:Database,chaEmotion:{[key:string]: [string,
|
||||
}
|
||||
|
||||
export function getAuthorNoteDefaultText(){
|
||||
const db = get(DataBase)
|
||||
const db = getDatabase()
|
||||
const template = db.promptTemplate
|
||||
if(!template){
|
||||
return ''
|
||||
@@ -428,12 +429,6 @@ export async function decryptBuffer(data:Uint8Array, keys:string){
|
||||
return result
|
||||
}
|
||||
|
||||
export function getCurrentCharacter(){
|
||||
const db = get(DataBase)
|
||||
const selectedChar = get(selectedCharID)
|
||||
return db.characters[selectedChar]
|
||||
}
|
||||
|
||||
export function toState<T>(t:T):Writable<T>{
|
||||
return writable(t)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user