Merge branch 'main' of https://github.com/kwaroran/RisuAI
This commit is contained in:
@@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"productName": "RisuAI",
|
"productName": "RisuAI",
|
||||||
"mainBinaryName": "RisuAI",
|
"mainBinaryName": "RisuAI",
|
||||||
"version": "152.0.1",
|
"version": "153.0.0",
|
||||||
"identifier": "co.aiclient.risu",
|
"identifier": "co.aiclient.risu",
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"updater": {
|
"updater": {
|
||||||
|
|||||||
@@ -174,6 +174,8 @@ export const languageEnglish = {
|
|||||||
presetChain: "If it is not blank, the preset will be changed and applied randomly every time when user sends a message in the preset list in this input. preset list should be seperated by comma, for example, `preset1,preset2`.",
|
presetChain: "If it is not blank, the preset will be changed and applied randomly every time when user sends a message in the preset list in this input. preset list should be seperated by comma, for example, `preset1,preset2`.",
|
||||||
legacyMediaFindings: "If enabled, it will use the old method to find media assets, without using the additional search algorithm.",
|
legacyMediaFindings: "If enabled, it will use the old method to find media assets, without using the additional search algorithm.",
|
||||||
comfyWorkflow: "Put the API workflow of comfy UI. you can get your API workflow in comfy UI by pressing the 'Workflow > Export (API)' button. you must also put {{risu_prompt}} in you workflow text. the {{risu_prompt}} will be replaced with the prompt provided by the Risu.",
|
comfyWorkflow: "Put the API workflow of comfy UI. you can get your API workflow in comfy UI by pressing the 'Workflow > Export (API)' button. you must also put {{risu_prompt}} in you workflow text. the {{risu_prompt}} will be replaced with the prompt provided by the Risu.",
|
||||||
|
automaticCachePoint: "Automatically creates cache point after the chat ends, if the caching point doesn't exist.",
|
||||||
|
experimentalChatCompressionDesc: "Compresses the unused chat data and saves in seperate file. this greatly reduces the size of the chat data, and greatly improves the performance, however its experimental and can be unstable, causing issues in backup feature and more.",
|
||||||
},
|
},
|
||||||
setup: {
|
setup: {
|
||||||
chooseProvider: "Choose AI Provider",
|
chooseProvider: "Choose AI Provider",
|
||||||
@@ -1068,7 +1070,6 @@ export const languageEnglish = {
|
|||||||
claudeCachingRetrival: "Claude Caching Retrival",
|
claudeCachingRetrival: "Claude Caching Retrival",
|
||||||
claudeCachingRetrivalDesc: "Extends the cache time for Claude Caching, by requesting every 4 minutes. this can reduce the cache miss rate, but it can increase the cost if its not used properly.",
|
claudeCachingRetrivalDesc: "Extends the cache time for Claude Caching, by requesting every 4 minutes. this can reduce the cache miss rate, but it can increase the cost if its not used properly.",
|
||||||
automaticCachePoint: "Automatic Cache Point",
|
automaticCachePoint: "Automatic Cache Point",
|
||||||
automaticCachePointDesc: "Automatically creates cache point after the chat ends, if the caching point doesn't exist.",
|
|
||||||
experimentalChatCompression: "Experimental Chat Data Handling",
|
experimentalChatCompression: "Experimental Chat Data Handling",
|
||||||
experimentalChatCompressionDesc: "Compresses the unused chat data and saves in seperate file.",
|
loadingChatData: "Loading Chat Data",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
import { getInlayAsset } from 'src/ts/process/files/inlays';
|
import { getInlayAsset } from 'src/ts/process/files/inlays';
|
||||||
import PlaygroundMenu from '../Playground/PlaygroundMenu.svelte';
|
import PlaygroundMenu from '../Playground/PlaygroundMenu.svelte';
|
||||||
import { ConnectionOpenStore } from 'src/ts/sync/multiuser';
|
import { ConnectionOpenStore } from 'src/ts/sync/multiuser';
|
||||||
|
import { coldStorageHeader, preLoadChat } from 'src/ts/process/coldstorage.svelte';
|
||||||
|
|
||||||
let messageInput:string = $state('')
|
let messageInput:string = $state('')
|
||||||
let messageInputTranslate:string = $state('')
|
let messageInputTranslate:string = $state('')
|
||||||
@@ -639,6 +640,15 @@
|
|||||||
)} {send}/>
|
)} {send}/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].message?.[0]?.data?.startsWith(coldStorageHeader) }
|
||||||
|
{#await preLoadChat($selectedCharID, DBState.db.characters[$selectedCharID].chatPage)}
|
||||||
|
<div class="w-full flex justify-center text-textcolor2 italic mb-12">
|
||||||
|
{language.loadingChatData}
|
||||||
|
</div>
|
||||||
|
{:then a}
|
||||||
|
<div></div>
|
||||||
|
{/await}
|
||||||
|
{:else}
|
||||||
{#each messageForm(DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].message, loadPages) as chat, i}
|
{#each messageForm(DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].message, loadPages) as chat, i}
|
||||||
{#if chat.role === 'char'}
|
{#if chat.role === 'char'}
|
||||||
{#if DBState.db.characters[$selectedCharID].type !== 'group'}
|
{#if DBState.db.characters[$selectedCharID].type !== 'group'}
|
||||||
@@ -683,6 +693,7 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
{#if DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].message.length <= loadPages}
|
{#if DBState.db.characters[$selectedCharID].chats[DBState.db.characters[$selectedCharID].chatPage].message.length <= loadPages}
|
||||||
{#if DBState.db.characters[$selectedCharID].type !== 'group' }
|
{#if DBState.db.characters[$selectedCharID].type !== 'group' }
|
||||||
<Chat
|
<Chat
|
||||||
@@ -736,6 +747,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{/if}
|
||||||
|
|
||||||
{#if openMenu}
|
{#if openMenu}
|
||||||
<div class="absolute right-2 bottom-16 p-5 bg-darkbg flex flex-col gap-3 text-textcolor rounded-md" onclick={(e) => {
|
<div class="absolute right-2 bottom-16 p-5 bg-darkbg flex flex-col gap-3 text-textcolor rounded-md" onclick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import Button from "src/lib/UI/GUI/Button.svelte";
|
import Button from "src/lib/UI/GUI/Button.svelte";
|
||||||
import { DBState } from 'src/ts/stores.svelte';
|
import { DBState } from 'src/ts/stores.svelte';
|
||||||
import { alertMd } from "src/ts/alert";
|
import { alertMd } from "src/ts/alert";
|
||||||
import { getRequestLog, isTauri } from "src/ts/globalApi.svelte";
|
import { getRequestLog, isNodeServer, isTauri } from "src/ts/globalApi.svelte";
|
||||||
import NumberInput from "src/lib/UI/GUI/NumberInput.svelte";
|
import NumberInput from "src/lib/UI/GUI/NumberInput.svelte";
|
||||||
import TextInput from "src/lib/UI/GUI/TextInput.svelte";
|
import TextInput from "src/lib/UI/GUI/TextInput.svelte";
|
||||||
import SelectInput from "src/lib/UI/GUI/SelectInput.svelte";
|
import SelectInput from "src/lib/UI/GUI/SelectInput.svelte";
|
||||||
@@ -162,12 +162,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center mt-4">
|
<div class="flex items-center mt-4">
|
||||||
<Check bind:check={DBState.db.automaticCachePoint} name={language.automaticCachePoint}>
|
<Check bind:check={DBState.db.automaticCachePoint} name={language.automaticCachePoint}>
|
||||||
<Help key="experimental"/><Help key="experimental"/>
|
<Help key="automaticCachePoint"/><Help key="experimental"/>
|
||||||
</Check>
|
</Check>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center mt-4">
|
<div class="flex items-center mt-4">
|
||||||
<Check bind:check={DBState.db.chatCompression} name={language.experimentalChatCompression}>
|
<Check bind:check={DBState.db.chatCompression} name={language.experimentalChatCompression}>
|
||||||
<Help key="experimental"/><Help key="experimental"/>
|
<Help key="experimentalChatCompressionDesc"/><Help key="experimental"/>
|
||||||
</Check>
|
</Check>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
import { getModuleToggles } from "src/ts/process/modules";
|
import { getModuleToggles } from "src/ts/process/modules";
|
||||||
import { language } from "src/lang";
|
import { language } from "src/lang";
|
||||||
import Toggles from "./Toggles.svelte";
|
import Toggles from "./Toggles.svelte";
|
||||||
import { preLoadChat } from "src/ts/process/coldstorage.svelte";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
chara: character|groupChat;
|
chara: character|groupChat;
|
||||||
@@ -68,6 +67,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
chara.chatPage = newChats.indexOf(chara.chats[currentChatPage])
|
||||||
chara.chats = newChats
|
chara.chats = newChats
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -76,10 +76,6 @@
|
|||||||
sorted += 1
|
sorted += 1
|
||||||
await sleep(1)
|
await sleep(1)
|
||||||
createStb()
|
createStb()
|
||||||
|
|
||||||
await preLoadChat($selectedCharID, newChats.indexOf(chara.chats[currentChatPage]))
|
|
||||||
chara.chatPage = newChats.indexOf(chara.chats[currentChatPage])
|
|
||||||
|
|
||||||
},
|
},
|
||||||
...sortableOptions
|
...sortableOptions
|
||||||
}))
|
}))
|
||||||
@@ -111,17 +107,14 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
chara.chatFolders = newFolders
|
chara.chatFolders = newFolders
|
||||||
|
chara.chatPage = newChats.indexOf(chara.chats[currentChatPage])
|
||||||
chara.chats = newChats
|
chara.chats = newChats
|
||||||
|
|
||||||
try {
|
try {
|
||||||
folderStb.destroy()
|
folderStb.destroy()
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
sorted += 1
|
sorted += 1
|
||||||
await sleep(1)
|
await sleep(1)
|
||||||
createStb()
|
createStb()
|
||||||
|
|
||||||
await preLoadChat($selectedCharID, newChats.indexOf(chara.chats[currentChatPage]))
|
|
||||||
chara.chatPage = newChats.indexOf(chara.chats[currentChatPage])
|
|
||||||
},
|
},
|
||||||
...sortableOptions
|
...sortableOptions
|
||||||
})
|
})
|
||||||
@@ -251,9 +244,8 @@
|
|||||||
<div></div>
|
<div></div>
|
||||||
{:else}
|
{:else}
|
||||||
{#each chara.chats.filter(chat => chat.folderId == chara.chatFolders[i].id) as chat}
|
{#each chara.chats.filter(chat => chat.folderId == chara.chatFolders[i].id) as chat}
|
||||||
<button data-risu-chat-idx={chara.chats.indexOf(chat)} onclick={async () => {
|
<button data-risu-chat-idx={chara.chats.indexOf(chat)} onclick={() => {
|
||||||
if(!editMode){
|
if(!editMode){
|
||||||
await preLoadChat($selectedCharID, chara.chats.indexOf(chat))
|
|
||||||
chara.chatPage = chara.chats.indexOf(chat)
|
chara.chatPage = chara.chats.indexOf(chat)
|
||||||
$ReloadGUIPointer += 1
|
$ReloadGUIPointer += 1
|
||||||
}
|
}
|
||||||
@@ -275,7 +267,6 @@
|
|||||||
const newChat = safeStructuredClone($state.snapshot(chara.chats[chara.chats.indexOf(chat)]))
|
const newChat = safeStructuredClone($state.snapshot(chara.chats[chara.chats.indexOf(chat)]))
|
||||||
newChat.name = `Copy of ${newChat.name}`
|
newChat.name = `Copy of ${newChat.name}`
|
||||||
chara.chats.unshift(newChat)
|
chara.chats.unshift(newChat)
|
||||||
await preLoadChat($selectedCharID, 0)
|
|
||||||
chara.chatPage = 0
|
chara.chatPage = 0
|
||||||
chara.chats = chara.chats
|
chara.chats = chara.chats
|
||||||
break
|
break
|
||||||
@@ -302,7 +293,6 @@
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 2:{
|
case 2:{
|
||||||
await preLoadChat($selectedCharID, chara.chats.indexOf(chat))
|
|
||||||
chara.chatPage = chara.chats.indexOf(chat)
|
chara.chatPage = chara.chats.indexOf(chat)
|
||||||
createMultiuserRoom()
|
createMultiuserRoom()
|
||||||
}
|
}
|
||||||
@@ -325,7 +315,6 @@
|
|||||||
}
|
}
|
||||||
}} class="text-textcolor2 hover:text-green-500 mr-1 cursor-pointer" onclick={async (e) => {
|
}} class="text-textcolor2 hover:text-green-500 mr-1 cursor-pointer" onclick={async (e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
await preLoadChat($selectedCharID, chara.chats.indexOf(chat))
|
|
||||||
exportChat(chara.chats.indexOf(chat))
|
exportChat(chara.chats.indexOf(chat))
|
||||||
}}>
|
}}>
|
||||||
<DownloadIcon size={18}/>
|
<DownloadIcon size={18}/>
|
||||||
@@ -342,7 +331,6 @@
|
|||||||
}
|
}
|
||||||
const d = await alertConfirm(`${language.removeConfirm}${chat.name}`)
|
const d = await alertConfirm(`${language.removeConfirm}${chat.name}`)
|
||||||
if(d){
|
if(d){
|
||||||
await preLoadChat($selectedCharID, 0)
|
|
||||||
chara.chatPage = 0
|
chara.chatPage = 0
|
||||||
$ReloadGUIPointer += 1
|
$ReloadGUIPointer += 1
|
||||||
let chats = chara.chats
|
let chats = chara.chats
|
||||||
@@ -364,9 +352,8 @@
|
|||||||
<div class="risu-chat flex flex-col">
|
<div class="risu-chat flex flex-col">
|
||||||
{#each chara.chats as chat, i}
|
{#each chara.chats as chat, i}
|
||||||
{#if chat.folderId == null}
|
{#if chat.folderId == null}
|
||||||
<button data-risu-chat-idx={i} onclick={async () => {
|
<button data-risu-chat-idx={i} onclick={() => {
|
||||||
if(!editMode){
|
if(!editMode){
|
||||||
await preLoadChat($selectedCharID, i)
|
|
||||||
chara.chatPage = i
|
chara.chatPage = i
|
||||||
$ReloadGUIPointer += 1
|
$ReloadGUIPointer += 1
|
||||||
}
|
}
|
||||||
@@ -390,7 +377,6 @@
|
|||||||
const newChat = safeStructuredClone($state.snapshot(chara.chats[i]))
|
const newChat = safeStructuredClone($state.snapshot(chara.chats[i]))
|
||||||
newChat.name = `Copy of ${newChat.name}`
|
newChat.name = `Copy of ${newChat.name}`
|
||||||
chara.chats.unshift(newChat)
|
chara.chats.unshift(newChat)
|
||||||
await preLoadChat($selectedCharID, 0)
|
|
||||||
chara.chatPage = 0
|
chara.chatPage = 0
|
||||||
chara.chats = chara.chats
|
chara.chats = chara.chats
|
||||||
break
|
break
|
||||||
@@ -418,7 +404,6 @@
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 2:{
|
case 2:{
|
||||||
await preLoadChat($selectedCharID, i)
|
|
||||||
chara.chatPage = i
|
chara.chatPage = i
|
||||||
createMultiuserRoom()
|
createMultiuserRoom()
|
||||||
}
|
}
|
||||||
@@ -457,7 +442,6 @@
|
|||||||
}
|
}
|
||||||
const d = await alertConfirm(`${language.removeConfirm}${chat.name}`)
|
const d = await alertConfirm(`${language.removeConfirm}${chat.name}`)
|
||||||
if(d){
|
if(d){
|
||||||
await preLoadChat($selectedCharID, 0)
|
|
||||||
chara.chatPage = 0
|
chara.chatPage = 0
|
||||||
$ReloadGUIPointer += 1
|
$ReloadGUIPointer += 1
|
||||||
let chats = chara.chats
|
let chats = chara.chats
|
||||||
|
|||||||
@@ -7,17 +7,64 @@ import {
|
|||||||
readDir,
|
readDir,
|
||||||
remove
|
remove
|
||||||
} from "@tauri-apps/plugin-fs"
|
} from "@tauri-apps/plugin-fs"
|
||||||
import { isTauri } from "../globalApi.svelte"
|
import { forageStorage, isNodeServer, isTauri } from "../globalApi.svelte"
|
||||||
import { DBState } from "../stores.svelte"
|
import { DBState } from "../stores.svelte"
|
||||||
|
import { hubURL } from "../characterCards"
|
||||||
|
import type { AccountStorage } from "../storage/accountStorage"
|
||||||
|
import type { NodeStorage } from "../storage/nodeStorage"
|
||||||
|
|
||||||
const coldStorageHeader = '\uEF01COLDSTORAGE\uEF01'
|
export const coldStorageHeader = '\uEF01COLDSTORAGE\uEF01'
|
||||||
|
|
||||||
|
async function decompress(data:Uint8Array) {
|
||||||
|
const fflate = await import('fflate')
|
||||||
|
return new Promise<Uint8Array>((resolve, reject) => {
|
||||||
|
fflate.decompress(data, (err, decompressed) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
resolve(decompressed)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async function getColdStorageItem(key:string) {
|
async function getColdStorageItem(key:string) {
|
||||||
|
|
||||||
if(isTauri){
|
if(forageStorage.isAccount){
|
||||||
|
const d = await fetch(hubURL + '/hub/account/coldstorage', {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'x-risu-key': key,
|
||||||
|
'x-risu-auth': (forageStorage.realStorage as AccountStorage).auth
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if(d.status === 200){
|
||||||
|
const buf = await d.arrayBuffer()
|
||||||
|
const text = new TextDecoder().decode(await decompress(new Uint8Array(buf)))
|
||||||
|
return JSON.parse(text)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
else if(isNodeServer){
|
||||||
try {
|
try {
|
||||||
const f = await readFile('./coldstorage/'+key+'.json')
|
const storage = forageStorage.realStorage as NodeStorage
|
||||||
const text = new TextDecoder().decode(f)
|
const f = await storage.getItem('coldstorage/' + key)
|
||||||
|
if(!f){
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
const text = new TextDecoder().decode(await decompress(new Uint8Array(f)))
|
||||||
|
return JSON.parse(text)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(isTauri){
|
||||||
|
try {
|
||||||
|
const f = await readFile('./coldstorage/'+key+'.json', {
|
||||||
|
baseDir: BaseDirectory.AppData
|
||||||
|
})
|
||||||
|
const text = new TextDecoder().decode(await decompress(new Uint8Array(f)))
|
||||||
return JSON.parse(text)
|
return JSON.parse(text)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return null
|
return null
|
||||||
@@ -36,7 +83,7 @@ async function getColdStorageItem(key:string) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const buf = await d.arrayBuffer()
|
const buf = await d.arrayBuffer()
|
||||||
const text = new TextDecoder().decode(buf)
|
const text = new TextDecoder().decode(await decompress(new Uint8Array(buf)))
|
||||||
return JSON.parse(text)
|
return JSON.parse(text)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return null
|
return null
|
||||||
@@ -45,13 +92,52 @@ async function getColdStorageItem(key:string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function setColdStorageItem(key:string, value:any) {
|
async function setColdStorageItem(key:string, value:any) {
|
||||||
if(isTauri){
|
|
||||||
|
const fflate = await import('fflate')
|
||||||
|
const json = JSON.stringify(value)
|
||||||
|
const compressed = await (new Promise<Uint8Array>((resolve, reject) => {
|
||||||
|
fflate.compress(new TextEncoder().encode(json), (err, compressed) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
resolve(compressed)
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
|
||||||
|
if(forageStorage.isAccount){
|
||||||
|
const res = await fetch(hubURL + '/hub/account/coldstorage', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'x-risu-key': key,
|
||||||
|
'x-risu-auth': (forageStorage.realStorage as AccountStorage).auth,
|
||||||
|
'content-type': 'application/json'
|
||||||
|
},
|
||||||
|
body: compressed
|
||||||
|
})
|
||||||
|
if(res.status !== 200){
|
||||||
|
try {
|
||||||
|
console.error('Error setting cold storage item')
|
||||||
|
console.error(await res.text())
|
||||||
|
} catch (error) {}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else if(isNodeServer){
|
||||||
|
try {
|
||||||
|
const storage = forageStorage.realStorage as NodeStorage
|
||||||
|
await storage.setItem('coldstorage/' + key, compressed)
|
||||||
|
return
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(isTauri){
|
||||||
try {
|
try {
|
||||||
if(!(await exists('./coldstorage'))){
|
if(!(await exists('./coldstorage'))){
|
||||||
await mkdir('./coldstorage', { recursive: true })
|
await mkdir('./coldstorage', { recursive: true, baseDir: BaseDirectory.AppData })
|
||||||
}
|
}
|
||||||
const text = JSON.stringify(value)
|
await writeFile('./coldstorage/'+key+'.json', compressed, { baseDir: BaseDirectory.AppData })
|
||||||
await writeFile('./coldstorage/'+key+'.json', new TextEncoder().encode(text))
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -62,8 +148,7 @@ async function setColdStorageItem(key:string, value:any) {
|
|||||||
const opfs = await navigator.storage.getDirectory()
|
const opfs = await navigator.storage.getDirectory()
|
||||||
const file = await opfs.getFileHandle('coldstorage_' + key+'.json', { create: true })
|
const file = await opfs.getFileHandle('coldstorage_' + key+'.json', { create: true })
|
||||||
const writable = await file.createWritable()
|
const writable = await file.createWritable()
|
||||||
const text = JSON.stringify(value)
|
await writable.write(compressed)
|
||||||
await writable.write(new TextEncoder().encode(text))
|
|
||||||
await writable.close()
|
await writable.close()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
@@ -92,6 +177,10 @@ async function removeColdStorageItem(key:string) {
|
|||||||
|
|
||||||
export async function makeColdData(){
|
export async function makeColdData(){
|
||||||
|
|
||||||
|
if(!DBState.db.chatCompression){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const currentTime = Date.now()
|
const currentTime = Date.now()
|
||||||
const coldTime = currentTime - 1000 * 60 * 60 * 24 * 30 //30 days before now
|
const coldTime = currentTime - 1000 * 60 * 60 * 24 * 30 //30 days before now
|
||||||
|
|
||||||
@@ -99,7 +188,7 @@ export async function makeColdData(){
|
|||||||
for(let j=0;j<DBState.db.characters[i].chats.length;j++){
|
for(let j=0;j<DBState.db.characters[i].chats.length;j++){
|
||||||
|
|
||||||
const chat = DBState.db.characters[i].chats[j]
|
const chat = DBState.db.characters[i].chats[j]
|
||||||
let greatestTime = 0
|
let greatestTime = chat.lastDate ?? 0
|
||||||
|
|
||||||
if(chat.message.length < 4){
|
if(chat.message.length < 4){
|
||||||
//it is inefficient to store small data
|
//it is inefficient to store small data
|
||||||
@@ -150,6 +239,7 @@ export async function preLoadChat(characterIndex:number, chatIndex:number){
|
|||||||
const coldData = await getColdStorageItem(coldDataKey)
|
const coldData = await getColdStorageItem(coldDataKey)
|
||||||
if(coldData){
|
if(coldData){
|
||||||
chat.message = coldData
|
chat.message = coldData
|
||||||
|
chat.lastDate = Date.now()
|
||||||
}
|
}
|
||||||
await setColdStorageItem(coldDataKey + '_accessMeta', {
|
await setColdStorageItem(coldDataKey + '_accessMeta', {
|
||||||
lastAccess: Date.now()
|
lastAccess: Date.now()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { defaultColorScheme, type ColorScheme } from '../gui/colorscheme';
|
|||||||
import type { PromptItem, PromptSettings } from '../process/prompt';
|
import type { PromptItem, PromptSettings } from '../process/prompt';
|
||||||
import type { OobaChatCompletionRequestParams } from '../model/ooba';
|
import type { OobaChatCompletionRequestParams } from '../model/ooba';
|
||||||
|
|
||||||
export let appVer = "152.0.1"
|
export let appVer = "153.0.0"
|
||||||
export let webAppSubVer = ''
|
export let webAppSubVer = ''
|
||||||
|
|
||||||
|
|
||||||
@@ -1333,6 +1333,7 @@ export interface Chat{
|
|||||||
fmIndex?:number
|
fmIndex?:number
|
||||||
hypaV3Data?:SerializableHypaV3Data
|
hypaV3Data?:SerializableHypaV3Data
|
||||||
folderId?:string
|
folderId?:string
|
||||||
|
lastDate?:number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChatFolder{
|
export interface ChatFolder{
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":"152.0.1"}
|
{"version":"153.0.0"}
|
||||||
Reference in New Issue
Block a user