Update to 0.8.0 (#42)
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "RisuAI",
|
"productName": "RisuAI",
|
||||||
"version": "0.7.9"
|
"version": "0.8.0"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const languageEnglish = {
|
|||||||
msgSound: "Plays *ding* sound when character responses",
|
msgSound: "Plays *ding* sound when character responses",
|
||||||
charDesc: "Brief description of the character. this effects characters response.",
|
charDesc: "Brief description of the character. this effects characters response.",
|
||||||
charFirstMessage: "First message of the character. this highly effects characters response.",
|
charFirstMessage: "First message of the character. this highly effects characters response.",
|
||||||
charNote: "a note that strongly effects model behavior. works in current chat. also known as memory.",
|
charNote: "a note that strongly effects model behavior. embbedded to current character. also known as UJB.",
|
||||||
toggleNsfw: "toggles NSFW/jailbreak prompt on and off.",
|
toggleNsfw: "toggles NSFW/jailbreak prompt on and off.",
|
||||||
lorebook: "Lorebook is a user-made dictionary for AI. AI only sees it when where is an activation keys in the context.",
|
lorebook: "Lorebook is a user-made dictionary for AI. AI only sees it when where is an activation keys in the context.",
|
||||||
loreName: "name of the lore. it dosen't effects the Ai.",
|
loreName: "name of the lore. it dosen't effects the Ai.",
|
||||||
@@ -54,13 +54,25 @@ export const languageEnglish = {
|
|||||||
regexScript: "Regex Script is a custom script that is embbedded to the character. it replaces string that matches IN to OUT.\n\nThere are three type options."
|
regexScript: "Regex Script is a custom script that is embbedded to the character. it replaces string that matches IN to OUT.\n\nThere are three type options."
|
||||||
+ "- **Modify Input** modifys user's input"
|
+ "- **Modify Input** modifys user's input"
|
||||||
+ "- **Modify Output** modifys character's output"
|
+ "- **Modify Output** modifys character's output"
|
||||||
+ "- **Modify Request Data** modifys current chat data when sent.\n\nIN must be a regex without flags and *\\*.\n\nOUT is a normal string."
|
+ "- **Modify Request Data** modifys current chat data when sent.\n\nIN must be a regex without flags and without slashes in start and end.\n\nOUT is a normal string."
|
||||||
+ "\n\n If OUT has {{data}} in string, it replaces to matched string."
|
+ "\n\n If OUT has {{data}} in string, it replaces to matched string."
|
||||||
+ "\n\n If OUT starts with **@@**, it doesn't replaces the string, but instead does a special effect if matching string founds."
|
+ "\n\n If OUT starts with **@@**, it doesn't replaces the string, but instead does a special effect if matching string founds."
|
||||||
+ "\n\n- @@emo (emotion name)\n\n if character is Emotion Images mode, sets (emotion name) as emotion and prevents default.",
|
+ "\n\n- @@emo (emotion name)\n\n if character is Emotion Images mode, sets (emotion name) as emotion and prevents default.",
|
||||||
experimental: "This is a experimental setting. it might be unstable.",
|
experimental: "This is a experimental setting. it might be unstable.",
|
||||||
oogaboogaURL: "If your WebUI supports older version of api, your url should look *like https:.../run/textgen*\n\n"
|
oogaboogaURL: "If your WebUI supports older version of api, your url should look *like https:.../run/textgen*\n\n"
|
||||||
+ "If your WebUI supports newVersion of api, your url should look like *https://.../api/v1/generate* and use the api server as host, and add --api to arguments."
|
+ "If your WebUI supports newVersion of api, your url should look like *https://.../api/v1/generate* and use the api server as host, and add --api to arguments.",
|
||||||
|
exampleMessage: "Example conversations that effects output of the character. it dosen't uses tokens permanently."
|
||||||
|
+ "\n\nExample format of conversations:"
|
||||||
|
+ "\n\n```\n<START>\n{{user}}: hi\n{{char}}: hello\n<START>\n{{user}}: hi\nHaruhi: hello\n```"
|
||||||
|
+ "\n\n```<START>``` Marks the beginning of a new conversation.",
|
||||||
|
creatorQuotes: "Note that appearances on top of first message. Used to inform users about this character. It doesn't go into prompt.",
|
||||||
|
systemPrompt: "A prompt that replaces main prompt in settings if its not blank.",
|
||||||
|
chatNote: "a note that strongly effects model behavior. embbedded to current chat. also known as memory.",
|
||||||
|
personality: "A brief description about character's personality. \n\n**It is not recommended to use this option. Describe it in character description instead.**",
|
||||||
|
scenario: "A brief description about character's scenario. \n\n**It is not recommended to use this option. Describe it in character description instead.**",
|
||||||
|
utilityBot: "When activated, it ignores main prompt. \n\n**It is not recommended to use this option. Modifiy system prompt instead.**",
|
||||||
|
loreSelective: "If Selective mode is toggled, both Activation Key and Secondary key should have a match to activate the lore."
|
||||||
|
|
||||||
},
|
},
|
||||||
setup: {
|
setup: {
|
||||||
chooseProvider: "Choose AI Provider",
|
chooseProvider: "Choose AI Provider",
|
||||||
@@ -211,6 +223,22 @@ export const languageEnglish = {
|
|||||||
editOutput: "Modfiy Output",
|
editOutput: "Modfiy Output",
|
||||||
editProcess: "Modfiy Request Data",
|
editProcess: "Modfiy Request Data",
|
||||||
loadLatest: "Load Latest Backup",
|
loadLatest: "Load Latest Backup",
|
||||||
loadOthers: "Load Other Backups"
|
loadOthers: "Load Other Backups",
|
||||||
|
exampleMessage: "Example Message",
|
||||||
|
creatorNotes: "Creator's Comment",
|
||||||
|
systemPrompt: "System Prompt",
|
||||||
|
characterNotes: "Character Notes",
|
||||||
|
personality: "Personality",
|
||||||
|
scenario: "Scenario",
|
||||||
|
alternateGreetings: "Alternate Greetings",
|
||||||
|
unrecommended: "Not Recommended",
|
||||||
|
chatNotes: "Chat Notes",
|
||||||
|
showUnrecommended: "Show Unrecommended Settings",
|
||||||
|
altGreet: "Alternative First Messages",
|
||||||
|
scripts: "Scripts",
|
||||||
|
settings: "Settings",
|
||||||
|
selective: "Selective",
|
||||||
|
SecondaryKeys: 'Secondary keys',
|
||||||
|
useGlobalSettings: "Use Global Settings",
|
||||||
|
recursiveScanning: "Recursive Scanning"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export const languageKorean = {
|
|||||||
regexScript: "정규식 스크립트는 캐릭터에 종속된 커스텀 스크립트입니다. IN의 조건에 맞는 문자열을 OUT으로 변경합니다.\n\n타입은 세가지가 있습니다."
|
regexScript: "정규식 스크립트는 캐릭터에 종속된 커스텀 스크립트입니다. IN의 조건에 맞는 문자열을 OUT으로 변경합니다.\n\n타입은 세가지가 있습니다."
|
||||||
+ "- **입력문 수정** 유저의 입력문을 수정합니다"
|
+ "- **입력문 수정** 유저의 입력문을 수정합니다"
|
||||||
+ "- **출력문 수정** 캐릭터의 출력문을 수정합니다"
|
+ "- **출력문 수정** 캐릭터의 출력문을 수정합니다"
|
||||||
+ "- **리퀘스트 데이터 수정** 리퀘스트를 보낼 때 채팅 데이터를 수정합니다.\n\nIN은 flag와 *\\* 가 없는 Regex여야 합니다.\n\nOUT은 일반 문자열입니다."
|
+ "- **리퀘스트 데이터 수정** 리퀘스트를 보낼 때 채팅 데이터를 수정합니다.\n\nIN은 flag가 없고, 양끝에 슬레시가 없는 Regex여야 합니다.\n\nOUT은 일반 문자열입니다."
|
||||||
+ "\n\n 만약 OUT 문자열에 {{data}}가 있으면, 매칭된 문자열로 바뀝니다."
|
+ "\n\n 만약 OUT 문자열에 {{data}}가 있으면, 매칭된 문자열로 바뀝니다."
|
||||||
+ "\n\n 만약 OUT이 @@로 시작된다면, 특수한 효과를 냅니다"
|
+ "\n\n 만약 OUT이 @@로 시작된다면, 특수한 효과를 냅니다"
|
||||||
+ "\n\n- @@emo (emotion name)\n\n 감정 이미지 모드일 시 (emotion name)을 감정으로 정하고 감정 처리를 하지 않습니다.",
|
+ "\n\n- @@emo (emotion name)\n\n 감정 이미지 모드일 시 (emotion name)을 감정으로 정하고 감정 처리를 하지 않습니다.",
|
||||||
@@ -208,5 +208,22 @@ export const languageKorean = {
|
|||||||
editOutput: "출력문 수정",
|
editOutput: "출력문 수정",
|
||||||
editProcess: "리퀘스트 데이터 수정",
|
editProcess: "리퀘스트 데이터 수정",
|
||||||
loadLatest: "가장 최근 백업 불러오기",
|
loadLatest: "가장 최근 백업 불러오기",
|
||||||
loadOthers: "다른 백업 불러오기"
|
loadOthers: "다른 백업 불러오기",
|
||||||
|
exampleMessage: "예시 대화",
|
||||||
|
creatorNotes: "제작자 코멘트",
|
||||||
|
systemPrompt: "시스템 프롬프트",
|
||||||
|
characterNotes: "캐릭터 노트",
|
||||||
|
personality: "성격",
|
||||||
|
scenario: "시나리오",
|
||||||
|
alternateGreetings: "추가 첫 메시지",
|
||||||
|
unrecommended: "비권장",
|
||||||
|
chatNotes: "채팅 노트",
|
||||||
|
showUnrecommended: "비권장 설정 보이기",
|
||||||
|
altGreet: "추가 첫 메시지",
|
||||||
|
scripts: "스크립트",
|
||||||
|
settings: "설정",
|
||||||
|
selective: "멀티플 키",
|
||||||
|
SecondaryKeys: '두번째 키',
|
||||||
|
useGlobalSettings: "글로벌 설정 사용",
|
||||||
|
recursiveScanning: "재귀 검색"
|
||||||
}
|
}
|
||||||
@@ -10,13 +10,14 @@
|
|||||||
import { replacePlaceholders } from "../../ts/util";
|
import { replacePlaceholders } from "../../ts/util";
|
||||||
export let message = ''
|
export let message = ''
|
||||||
export let name = ''
|
export let name = ''
|
||||||
export let img = ''
|
export let img:string|Promise<string> = ''
|
||||||
export let idx = -1
|
export let idx = -1
|
||||||
export let rerollIcon = false
|
export let rerollIcon = false
|
||||||
export let onReroll = () => {}
|
export let onReroll = () => {}
|
||||||
export let unReroll = () => {}
|
export let unReroll = () => {}
|
||||||
let translating = false
|
let translating = false
|
||||||
let editMode = false
|
let editMode = false
|
||||||
|
export let altGreeting = false
|
||||||
|
|
||||||
let msgDisplay = ''
|
let msgDisplay = ''
|
||||||
|
|
||||||
@@ -60,15 +61,13 @@
|
|||||||
|
|
||||||
$: displaya(message)
|
$: displaya(message)
|
||||||
</script>
|
</script>
|
||||||
<div class="flex">
|
<div class="flex max-w-full">
|
||||||
<div class="text-neutral-200 mt-2 p-2 bg-transparent flex-grow ml-4 mr-4 border-t-gray-900 border-opacity-30 border-transparent flexium items-start">
|
<div class="text-neutral-200 mt-2 p-2 bg-transparent flex-grow ml-4 mr-4 border-t-gray-900 border-opacity-30 border-transparent flexium items-start">
|
||||||
{#if img === ''}
|
{#await img}
|
||||||
<div class="rounded-md shadow-lg bg-gray-500 mt-2" style={`height:${$DataBase.iconsize * 3.5 / 100}rem;width:${$DataBase.iconsize * 3.5 / 100}rem`}>
|
<div class="rounded-md shadow-lg bg-gray-500 mt-2" style={`height:${$DataBase.iconsize * 3.5 / 100}rem;width:${$DataBase.iconsize * 3.5 / 100}rem`} />
|
||||||
|
{:then m}
|
||||||
</div>
|
<div class="rounded-md shadow-lg bg-gray-500 mt-2" style={m + `height:${$DataBase.iconsize * 3.5 / 100}rem;width:${$DataBase.iconsize * 3.5 / 100}rem`} />
|
||||||
{:else}
|
{/await}
|
||||||
<div class="rounded-md shadow-lg bg-gray-500 mt-2" style={img + `height:${$DataBase.iconsize * 3.5 / 100}rem;width:${$DataBase.iconsize * 3.5 / 100}rem`} />
|
|
||||||
{/if}
|
|
||||||
<span class="flex flex-col ml-4 w-full">
|
<span class="flex flex-col ml-4 w-full">
|
||||||
<div class="flexium items-center chat">
|
<div class="flexium items-center chat">
|
||||||
<span class="chat text-xl unmargin">{name}</span>
|
<span class="chat text-xl unmargin">{name}</span>
|
||||||
@@ -106,8 +105,8 @@
|
|||||||
<LanguagesIcon />
|
<LanguagesIcon />
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if rerollIcon}
|
{#if rerollIcon || altGreeting}
|
||||||
{#if $DataBase.swipe}
|
{#if $DataBase.swipe || altGreeting}
|
||||||
<button class="ml-2 hover:text-green-500 transition-colors" on:click={unReroll}>
|
<button class="ml-2 hover:text-green-500 transition-colors" on:click={unReroll}>
|
||||||
<ArrowLeft size={22}/>
|
<ArrowLeft size={22}/>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
20
src/lib/ChatScreens/CreatorQuote.svelte
Normal file
20
src/lib/ChatScreens/CreatorQuote.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<div class="flex w-full justify-center mt-4 max-w-100vw">
|
||||||
|
<div class="w-5/6 max-w-80vw bg-darkbg rounded-md p-3 text-white text-sm">
|
||||||
|
<h1 class="font-bold mb-2">{language.creatorNotes}
|
||||||
|
<button class="float-right" on:click={onRemove}>
|
||||||
|
<XIcon />
|
||||||
|
</button>
|
||||||
|
</h1>
|
||||||
|
<div class="ml-2 max-w-full break-words text chat chattext prose prose-invert">
|
||||||
|
{@html ParseMarkdown(quote)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script lang="ts">
|
||||||
|
import { XIcon } from "lucide-svelte";
|
||||||
|
import { language } from "src/lang";
|
||||||
|
import { ParseMarkdown } from "src/ts/parser";
|
||||||
|
|
||||||
|
export let onRemove: () => void
|
||||||
|
export let quote:string
|
||||||
|
</script>
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
import {cloneDeep} from 'lodash'
|
import {cloneDeep} from 'lodash'
|
||||||
import { processScript } from "src/ts/process/scripts";
|
import { processScript } from "src/ts/process/scripts";
|
||||||
import GithubStars from "../Others/GithubStars.svelte";
|
import GithubStars from "../Others/GithubStars.svelte";
|
||||||
|
import CreatorQuote from "./CreatorQuote.svelte";
|
||||||
|
|
||||||
let messageInput = ''
|
let messageInput = ''
|
||||||
let openMenu = false
|
let openMenu = false
|
||||||
@@ -237,88 +238,81 @@
|
|||||||
{#each messageForm($DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message, loadPages) as chat, i}
|
{#each messageForm($DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message, loadPages) as chat, i}
|
||||||
{#if chat.role === 'char'}
|
{#if chat.role === 'char'}
|
||||||
{#if $DataBase.characters[$selectedCharID].type !== 'group'}
|
{#if $DataBase.characters[$selectedCharID].type !== 'group'}
|
||||||
{#await getCharImage($DataBase.characters[$selectedCharID].image, 'css')}
|
<Chat
|
||||||
<Chat
|
idx={chat.index}
|
||||||
idx={chat.index}
|
name={$DataBase.characters[$selectedCharID].name}
|
||||||
name={$DataBase.characters[$selectedCharID].name}
|
message={chat.data}
|
||||||
message={chat.data}
|
img={getCharImage($DataBase.characters[$selectedCharID].image, 'css')}
|
||||||
img={''}
|
rerollIcon={i === 0}
|
||||||
rerollIcon={i === 0}
|
onReroll={reroll}
|
||||||
onReroll={reroll}
|
unReroll={unReroll}
|
||||||
unReroll={unReroll}
|
/>
|
||||||
/>
|
|
||||||
{:then im}
|
|
||||||
<Chat
|
|
||||||
idx={chat.index}
|
|
||||||
name={$DataBase.characters[$selectedCharID].name}
|
|
||||||
message={chat.data}
|
|
||||||
img={im}
|
|
||||||
rerollIcon={i === 0}
|
|
||||||
onReroll={reroll}
|
|
||||||
unReroll={unReroll}
|
|
||||||
|
|
||||||
/>
|
|
||||||
{/await}
|
|
||||||
{:else}
|
{:else}
|
||||||
{#await getCharImage(findCharacterbyId(chat.saying).image, 'css')}
|
<Chat
|
||||||
<Chat
|
idx={chat.index}
|
||||||
idx={chat.index}
|
name={findCharacterbyId(chat.saying).name}
|
||||||
name={findCharacterbyId(chat.saying).name}
|
rerollIcon={i === 0}
|
||||||
message={chat.data}
|
message={chat.data}
|
||||||
rerollIcon={i === 0}
|
onReroll={reroll}
|
||||||
onReroll={reroll}
|
unReroll={unReroll}
|
||||||
unReroll={unReroll}
|
img={getCharImage(findCharacterbyId(chat.saying).image, 'css')}
|
||||||
img={''}
|
/>
|
||||||
/>
|
|
||||||
{:then im}
|
|
||||||
<Chat
|
|
||||||
idx={chat.index}
|
|
||||||
name={findCharacterbyId(chat.saying).name}
|
|
||||||
rerollIcon={i === 0}
|
|
||||||
message={chat.data}
|
|
||||||
onReroll={reroll}
|
|
||||||
unReroll={unReroll}
|
|
||||||
img={im}
|
|
||||||
/>
|
|
||||||
{/await}
|
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
{#await getCharImage($DataBase.userIcon, 'css')}
|
<Chat
|
||||||
<Chat
|
idx={chat.index}
|
||||||
idx={chat.index}
|
name={$DataBase.username}
|
||||||
name={$DataBase.username}
|
message={chat.data}
|
||||||
message={chat.data}
|
img={getCharImage($DataBase.userIcon, 'css')}
|
||||||
img={''}
|
/>
|
||||||
/>
|
|
||||||
{:then im}
|
|
||||||
<Chat
|
|
||||||
idx={chat.index}
|
|
||||||
name={$DataBase.username}
|
|
||||||
message={chat.data}
|
|
||||||
img={im}
|
|
||||||
/>
|
|
||||||
{/await}
|
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{#if $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message.length <= loadPages}
|
{#if $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message.length <= loadPages}
|
||||||
{#if $DataBase.characters[$selectedCharID].type !== 'group'}
|
{#if $DataBase.characters[$selectedCharID].type !== 'group'}
|
||||||
{#await getCharImage($DataBase.characters[$selectedCharID].image, 'css')}
|
<Chat
|
||||||
<Chat
|
name={$DataBase.characters[$selectedCharID].name}
|
||||||
name={$DataBase.characters[$selectedCharID].name}
|
message={$DataBase.characters[$selectedCharID].firstMsgIndex === -1 ? $DataBase.characters[$selectedCharID].firstMessage :
|
||||||
message={ $DataBase.characters[$selectedCharID].firstMessage}
|
$DataBase.characters[$selectedCharID].alternateGreetings[$DataBase.characters[$selectedCharID].firstMsgIndex]}
|
||||||
img={''}
|
img={getCharImage($DataBase.characters[$selectedCharID].image, 'css')}
|
||||||
idx={-1}
|
idx={-1}
|
||||||
/>
|
altGreeting={$DataBase.characters[$selectedCharID].alternateGreetings.length > 0}
|
||||||
{:then im}
|
onReroll={() => {
|
||||||
<Chat
|
const cha = $DataBase.characters[$selectedCharID]
|
||||||
name={$DataBase.characters[$selectedCharID].name}
|
if(cha.type !== 'group'){
|
||||||
message={ $DataBase.characters[$selectedCharID].firstMessage}
|
if (cha.firstMsgIndex >= (cha.alternateGreetings.length - 1)){
|
||||||
img={im}
|
cha.firstMsgIndex = -1
|
||||||
idx={-1}
|
}
|
||||||
/>
|
else{
|
||||||
{/await}
|
cha.firstMsgIndex += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$DataBase.characters[$selectedCharID] = cha
|
||||||
|
}}
|
||||||
|
unReroll={() => {
|
||||||
|
const cha = $DataBase.characters[$selectedCharID]
|
||||||
|
if(cha.type !== 'group'){
|
||||||
|
if (cha.firstMsgIndex === -1){
|
||||||
|
cha.firstMsgIndex = (cha.alternateGreetings.length - 1)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
cha.firstMsgIndex -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$DataBase.characters[$selectedCharID] = cha
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{#if !$DataBase.characters[$selectedCharID].removedQuotes && $DataBase.characters[$selectedCharID].creatorNotes.length >= 2}
|
||||||
|
<CreatorQuote quote={$DataBase.characters[$selectedCharID].creatorNotes} onRemove={() => {
|
||||||
|
const cha = $DataBase.characters[$selectedCharID]
|
||||||
|
if(cha.type !== 'group'){
|
||||||
|
cha.removedQuotes = true
|
||||||
|
}
|
||||||
|
$DataBase.characters[$selectedCharID] = cha
|
||||||
|
}} />
|
||||||
|
{/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-gray-200" on:click={(e) => {
|
<div class="absolute right-2 bottom-16 p-5 bg-darkbg flex flex-col gap-3 text-gray-200" on:click={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|||||||
@@ -5,15 +5,20 @@
|
|||||||
}}>
|
}}>
|
||||||
{#if key === "experimental"}
|
{#if key === "experimental"}
|
||||||
<FlaskConicalIcon size={14} />
|
<FlaskConicalIcon size={14} />
|
||||||
|
{:else if unrecommended}
|
||||||
|
<div class="text-red-500 hover:text-green-500">
|
||||||
|
<AlertTriangle size={14} />
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<HelpCircleIcon size={14} />
|
<HelpCircleIcon size={14} />
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { FlaskConicalIcon, HelpCircleIcon } from "lucide-svelte";
|
import { AlertTriangle, FlaskConicalIcon, HelpCircleIcon } from "lucide-svelte";
|
||||||
import { language } from "src/lang";
|
import { language } from "src/lang";
|
||||||
import { alertMd } from "src/ts/alert";
|
import { alertMd } from "src/ts/alert";
|
||||||
|
|
||||||
|
export let unrecommended = false
|
||||||
export let key: (keyof (typeof language.help))
|
export let key: (keyof (typeof language.help))
|
||||||
</script>
|
</script>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
import { tokenize } from "../../ts/tokenizer";
|
import { tokenize } from "../../ts/tokenizer";
|
||||||
import { DataBase, type Database, type character, type groupChat } from "../../ts/database";
|
import { DataBase, type Database, type character, type groupChat } from "../../ts/database";
|
||||||
import { selectedCharID } from "../../ts/stores";
|
import { selectedCharID } from "../../ts/stores";
|
||||||
import { PlusIcon, SmileIcon, TrashIcon, UserIcon, ActivityIcon, BookIcon, LoaderIcon, User } from 'lucide-svelte'
|
import { PlusIcon, SmileIcon, TrashIcon, UserIcon, ActivityIcon, BookIcon, LoaderIcon, User, DnaIcon, CurlyBracesIcon } from 'lucide-svelte'
|
||||||
import Check from "../Others/Check.svelte";
|
import Check from "../Others/Check.svelte";
|
||||||
import { addCharEmotion, addingEmotion, getCharImage, rmCharEmotion, selectCharImg, makeGroupImage } from "../../ts/characters";
|
import { addCharEmotion, addingEmotion, getCharImage, rmCharEmotion, selectCharImg, makeGroupImage } from "../../ts/characters";
|
||||||
import LoreBook from "./LoreBookSetting.svelte";
|
import LoreBook from "./LoreBookSetting.svelte";
|
||||||
@@ -22,13 +22,15 @@
|
|||||||
let tokens = {
|
let tokens = {
|
||||||
desc: 0,
|
desc: 0,
|
||||||
firstMsg: 0,
|
firstMsg: 0,
|
||||||
localNote: 0
|
localNote: 0,
|
||||||
|
charaNote: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
let lasttokens = {
|
let lasttokens = {
|
||||||
desc: '',
|
desc: '',
|
||||||
firstMsg: '',
|
firstMsg: '',
|
||||||
localNote: ''
|
localNote: '',
|
||||||
|
charaNote: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadTokenize(chara){
|
async function loadTokenize(chara){
|
||||||
@@ -45,12 +47,18 @@
|
|||||||
lasttokens.firstMsg = chara.firstMessage
|
lasttokens.firstMsg = chara.firstMessage
|
||||||
tokens.firstMsg = await tokenize(chara.firstMessage)
|
tokens.firstMsg = await tokenize(chara.firstMessage)
|
||||||
}
|
}
|
||||||
|
if(lasttokens.charaNote !== chara.postHistoryInstructions){
|
||||||
|
lasttokens.charaNote = chara.postHistoryInstructions
|
||||||
|
tokens.charaNote = await tokenize(chara.postHistoryInstructions)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(lasttokens.localNote !== currentChar.data.chats[currentChar.data.chatPage].note){
|
if(lasttokens.localNote !== currentChar.data.chats[currentChar.data.chatPage].note){
|
||||||
lasttokens.localNote = currentChar.data.chats[currentChar.data.chatPage].note
|
lasttokens.localNote = currentChar.data.chats[currentChar.data.chatPage].note
|
||||||
tokens.localNote = await tokenize(currentChar.data.chats[currentChar.data.chatPage].note)
|
tokens.localNote = await tokenize(currentChar.data.chats[currentChar.data.chatPage].note)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -148,6 +156,11 @@
|
|||||||
<button class={subMenu === 3 ? 'text-gray-200' : 'text-gray-500'} on:click={() => {subMenu = 3;subberMenu = 0}}>
|
<button class={subMenu === 3 ? 'text-gray-200' : 'text-gray-500'} on:click={() => {subMenu = 3;subberMenu = 0}}>
|
||||||
<BookIcon />
|
<BookIcon />
|
||||||
</button>
|
</button>
|
||||||
|
{#if currentChar.type === 'character'}
|
||||||
|
<button class={subMenu === 4 ? 'text-gray-200' : 'text-gray-500'} on:click={() => {subMenu = 4}}>
|
||||||
|
<CurlyBracesIcon />
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
<button class={subMenu === 2 ? 'text-gray-200' : 'text-gray-500'} on:click={() => {subMenu = 2}}>
|
<button class={subMenu === 2 ? 'text-gray-200' : 'text-gray-500'} on:click={() => {subMenu = 2}}>
|
||||||
<ActivityIcon />
|
<ActivityIcon />
|
||||||
</button>
|
</button>
|
||||||
@@ -163,6 +176,10 @@
|
|||||||
<span class="text-neutral-200">{language.firstMessage} <Help key="charFirstMessage"/></span>
|
<span class="text-neutral-200">{language.firstMessage} <Help key="charFirstMessage"/></span>
|
||||||
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 text-xs resize-none h-20 focus:bg-selected" autocomplete="off" bind:value={currentChar.data.firstMessage}></textarea>
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 text-xs resize-none h-20 focus:bg-selected" autocomplete="off" bind:value={currentChar.data.firstMessage}></textarea>
|
||||||
<span class="text-gray-400 mb-6 text-sm">{tokens.firstMsg} {language.tokens}</span>
|
<span class="text-gray-400 mb-6 text-sm">{tokens.firstMsg} {language.tokens}</span>
|
||||||
|
<span class="text-neutral-200">{language.authorNote} <Help key="charNote"/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none h-20 focus:bg-selected text-xs" autocomplete="off" bind:value={currentChar.data.postHistoryInstructions}></textarea>
|
||||||
|
<span class="text-gray-400 mb-6 text-sm">{tokens.charaNote} {language.tokens}</span>
|
||||||
|
|
||||||
{:else}
|
{:else}
|
||||||
<input class="text-neutral-200 mt-2 mb-4 p-2 bg-transparent input-text text-xl focus:bg-selected" placeholder="Group Name" bind:value={currentChar.data.name}>
|
<input class="text-neutral-200 mt-2 mb-4 p-2 bg-transparent input-text text-xl focus:bg-selected" placeholder="Group Name" bind:value={currentChar.data.name}>
|
||||||
<span class="text-neutral-200">{language.character}</span>
|
<span class="text-neutral-200">{language.character}</span>
|
||||||
@@ -191,11 +208,13 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<span class="text-neutral-200">{language.chatNotes} <Help key="charNote"/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none h-20 focus:bg-selected text-xs" autocomplete="off" bind:value={currentChar.data.chats[currentChar.data.chatPage].note}></textarea>
|
||||||
|
<span class="text-gray-400 mb-6 text-sm">{tokens.localNote} {language.tokens}</span>
|
||||||
|
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
<span class="text-neutral-200">{language.authorNote} <Help key="charNote"/></span>
|
|
||||||
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none h-20 focus:bg-selected text-xs" autocomplete="off" bind:value={currentChar.data.chats[currentChar.data.chatPage].note}></textarea>
|
|
||||||
<span class="text-gray-400 mb-6 text-sm">{tokens.localNote} {language.tokens}</span>
|
|
||||||
|
|
||||||
<div class="flex mt-6 items-center">
|
<div class="flex mt-6 items-center">
|
||||||
<Check bind:check={$DataBase.jailbreakToggle}/>
|
<Check bind:check={$DataBase.jailbreakToggle}/>
|
||||||
<span class="text-neutral-200 ml-2">{language.jailbreakToggle}</span>
|
<span class="text-neutral-200 ml-2">{language.jailbreakToggle}</span>
|
||||||
@@ -356,9 +375,10 @@
|
|||||||
{:else if subMenu === 3}
|
{:else if subMenu === 3}
|
||||||
<h2 class="mb-2 text-2xl font-bold mt-2">{language.loreBook} <Help key="lorebook"/></h2>
|
<h2 class="mb-2 text-2xl font-bold mt-2">{language.loreBook} <Help key="lorebook"/></h2>
|
||||||
<LoreBook />
|
<LoreBook />
|
||||||
{:else if subMenu === 2}
|
{:else if subMenu === 4}
|
||||||
<h2 class="mb-2 text-2xl font-bold mt-2">{language.advancedSettings}</h2>
|
{#if currentChar.type === 'character'}
|
||||||
{#if currentChar.type !== 'group'}
|
<h2 class="mb-2 text-2xl font-bold mt-2">{language.scripts}</h2>
|
||||||
|
|
||||||
<span class="text-neutral-200 mt-2">Bias <Help key="bias"/></span>
|
<span class="text-neutral-200 mt-2">Bias <Help key="bias"/></span>
|
||||||
<table class="contain w-full max-w-full tabler mt-2">
|
<table class="contain w-full max-w-full tabler mt-2">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -374,7 +394,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
{#if currentChar.data.bias.length === 0}
|
{#if currentChar.data.bias.length === 0}
|
||||||
<tr>
|
<tr>
|
||||||
<div class="text-gray-500">{language.noBias}</div>
|
<div class="text-gray-500"> {language.noBias}</div>
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
{#each currentChar.data.bias as bias, i}
|
{#each currentChar.data.bias as bias, i}
|
||||||
@@ -394,7 +414,9 @@
|
|||||||
}}><TrashIcon /></button>
|
}}><TrashIcon /></button>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<span class="text-neutral-200 mt-4">{language.regexScript} <Help key="regexScript"/></span>
|
<span class="text-neutral-200 mt-4">{language.regexScript} <Help key="regexScript"/></span>
|
||||||
<table class="contain w-full max-w-full tabler mt-2 flex flex-col p-2 gap-2">
|
<table class="contain w-full max-w-full tabler mt-2 flex flex-col p-2 gap-2">
|
||||||
{#if currentChar.data.customscript.length === 0}
|
{#if currentChar.data.customscript.length === 0}
|
||||||
@@ -410,7 +432,7 @@
|
|||||||
}}/>
|
}}/>
|
||||||
{/each}
|
{/each}
|
||||||
</table>
|
</table>
|
||||||
<th class="font-medium cursor-pointer hover:text-green-500" on:click={() => {
|
<button class="font-medium cursor-pointer hover:text-green-500 mb-2" on:click={() => {
|
||||||
if(currentChar.type === 'character'){
|
if(currentChar.type === 'character'){
|
||||||
let script = currentChar.data.customscript
|
let script = currentChar.data.customscript
|
||||||
script.push({
|
script.push({
|
||||||
@@ -421,21 +443,95 @@
|
|||||||
})
|
})
|
||||||
currentChar.data.customscript = script
|
currentChar.data.customscript = script
|
||||||
}
|
}
|
||||||
}}><PlusIcon /></th>
|
}}><PlusIcon /></button>
|
||||||
<div class="flex items-center mt-4">
|
{/if}
|
||||||
<Check bind:check={currentChar.data.utilityBot}/>
|
{:else if subMenu === 2}
|
||||||
<span>{language.utilityBot}</span>
|
<h2 class="mb-2 text-2xl font-bold mt-2">{language.advancedSettings}</h2>
|
||||||
</div>
|
{#if currentChar.type !== 'group'}
|
||||||
|
<span class="text-neutral-200">{language.exampleMessage} <Help key="exampleMessage"/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 text-xs resize-none h-20 focus:bg-selected" autocomplete="off" bind:value={currentChar.data.exampleMessage}></textarea>
|
||||||
|
|
||||||
|
<span class="text-neutral-200">{language.creatorNotes} <Help key="creatorQuotes"/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 text-xs resize-none h-20 focus:bg-selected" autocomplete="off" bind:value={currentChar.data.creatorNotes} on:input={() => {
|
||||||
|
currentChar.data.removedQuotes = false
|
||||||
|
}}></textarea>
|
||||||
|
|
||||||
|
<span class="text-neutral-200">{language.systemPrompt} <Help key="systemPrompt"/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 text-xs resize-none h-20 focus:bg-selected" autocomplete="off" bind:value={currentChar.data.systemPrompt}></textarea>
|
||||||
|
|
||||||
|
<span class="text-neutral-200">{language.chatNotes} <Help key="chatNote"/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 resize-none h-20 focus:bg-selected text-xs" autocomplete="off" bind:value={currentChar.data.chats[currentChar.data.chatPage].note}></textarea>
|
||||||
|
<span class="text-gray-400 mb-6 text-sm">{tokens.localNote} {language.tokens}</span>
|
||||||
|
|
||||||
|
{#if $DataBase.showUnrecommended || currentChar.data.personality.length > 3}
|
||||||
|
<span class="text-neutral-200">{language.personality} <Help key="personality" unrecommended/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 text-xs resize-none h-20 focus:bg-selected" autocomplete="off" bind:value={currentChar.data.personality}></textarea>
|
||||||
|
{/if}
|
||||||
|
{#if $DataBase.showUnrecommended || currentChar.data.scenario.length > 3}
|
||||||
|
<span class="text-neutral-200">{language.scenario} <Help key="scenario" unrecommended/></span>
|
||||||
|
<textarea class="bg-transparent input-text mt-2 mb-2 text-gray-200 text-xs resize-none h-20 focus:bg-selected" autocomplete="off" bind:value={currentChar.data.scenario}></textarea>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<span class="text-neutral-200 mt-2">{language.altGreet}</span>
|
||||||
|
<table class="contain w-full max-w-full tabler mt-2">
|
||||||
|
<tr>
|
||||||
|
<th class="font-medium">{language.value}</th>
|
||||||
|
<th class="font-medium cursor-pointer w-10">
|
||||||
|
<button class="hover:text-green-500" on:click={() => {
|
||||||
|
if(currentChar.type === 'character'){
|
||||||
|
let alternateGreetings = currentChar.data.alternateGreetings
|
||||||
|
alternateGreetings.push('')
|
||||||
|
currentChar.data.alternateGreetings = alternateGreetings
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<PlusIcon />
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
{#if currentChar.data.alternateGreetings.length === 0}
|
||||||
|
<tr>
|
||||||
|
<div class="text-gray-500"> No Messages</div>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{#each currentChar.data.alternateGreetings as bias, i}
|
||||||
|
<tr>
|
||||||
|
<td class="font-medium truncate">
|
||||||
|
<textarea class="text-neutral-200 mt-2 mb-4 p-2 bg-transparent input-text focus:bg-selected w-full resize-none" bind:value={currentChar.data.alternateGreetings[i]} placeholder="..." />
|
||||||
|
</td>
|
||||||
|
<th class="font-medium cursor-pointer w-10">
|
||||||
|
<button class="hover:text-green-500" on:click={() => {
|
||||||
|
if(currentChar.type === 'character'){
|
||||||
|
currentChar.data.firstMsgIndex = -1
|
||||||
|
let alternateGreetings = currentChar.data.alternateGreetings
|
||||||
|
alternateGreetings.splice(i, 1)
|
||||||
|
currentChar.data.alternateGreetings = alternateGreetings
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
<TrashIcon />
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
{#if $DataBase.showUnrecommended || currentChar.data.utilityBot}
|
||||||
|
<div class="flex items-center mt-4">
|
||||||
|
<Check bind:check={currentChar.data.utilityBot}/>
|
||||||
|
<span>{language.utilityBot} <Help key="utilityBot" unrecommended/></span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<button on:click={async () => {
|
<button on:click={async () => {
|
||||||
exportChar($selectedCharID)
|
exportChar($selectedCharID)
|
||||||
}} class="text-neutral-200 mt-6 text-lg bg-transparent border-solid border-1 border-borderc p-4 hover:bg-green-500 transition-colors cursor-pointer">{language.exportCharacter}</button>
|
}} class="text-neutral-200 mt-6 text-lg bg-transparent border-solid border-1 border-borderc p-4 hover:bg-green-500 transition-colors cursor-pointer">{language.exportCharacter}</button>
|
||||||
|
|
||||||
{:else}
|
{:else}
|
||||||
|
|
||||||
<div class="flex mb-2 items-center">
|
<div class="flex mb-2 items-center">
|
||||||
<Check bind:check={currentChar.data.useCharacterLore}/>
|
<Check bind:check={currentChar.data.useCharacterLore}/>
|
||||||
<span class="text-neutral-200 ml-2">{language.useCharLorebook} <Help key="experimental"/></span>
|
<span class="text-neutral-200 ml-2">{language.useCharLorebook} <Help key="experimental"/></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
<button on:click={async () => {
|
<button on:click={async () => {
|
||||||
|
|||||||
@@ -13,9 +13,10 @@
|
|||||||
<div class="w-full flex flex-col">
|
<div class="w-full flex flex-col">
|
||||||
<div class="flex items-center transition-colors w-full ">
|
<div class="flex items-center transition-colors w-full ">
|
||||||
<button class="endflex valuer border-borderc" on:click={() => {
|
<button class="endflex valuer border-borderc" on:click={() => {
|
||||||
|
value.secondkey = value.secondkey ?? ''
|
||||||
open = !open
|
open = !open
|
||||||
}}>
|
}}>
|
||||||
<span>{value.comment.length === 0 ? 'Unnamed Lore' : value.comment}</span>
|
<span>{value.comment.length === 0 ? value.key.length === 0 ? "Unnamed Lore" : value.key : value.comment}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="valuer" on:click={async () => {
|
<button class="valuer" on:click={async () => {
|
||||||
const d = await alertConfirm(language.removeConfirm + value.comment)
|
const d = await alertConfirm(language.removeConfirm + value.comment)
|
||||||
@@ -34,15 +35,25 @@
|
|||||||
<span class="text-neutral-200 mt-6">{language.activationKeys} <Help key="loreActivationKey"/></span>
|
<span class="text-neutral-200 mt-6">{language.activationKeys} <Help key="loreActivationKey"/></span>
|
||||||
<span class="text-xs text-gray-500">{language.activationKeysInfo}</span>
|
<span class="text-xs text-gray-500">{language.activationKeysInfo}</span>
|
||||||
<input class="text-neutral-200 p-2 bg-transparent input-text focus:bg-selected text-sm" bind:value={value.key}>
|
<input class="text-neutral-200 p-2 bg-transparent input-text focus:bg-selected text-sm" bind:value={value.key}>
|
||||||
|
|
||||||
|
{#if value.selective}
|
||||||
|
<span class="text-neutral-200 mt-6">{language.SecondaryKeys}</span>
|
||||||
|
<span class="text-xs text-gray-500">{language.activationKeysInfo}</span>
|
||||||
|
<input class="text-neutral-200 p-2 bg-transparent input-text focus:bg-selected text-sm" bind:value={value.secondkey}>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
<span class="text-neutral-200 mt-4">{language.insertOrder} <Help key="loreorder"/></span>
|
<span class="text-neutral-200 mt-4">{language.insertOrder} <Help key="loreorder"/></span>
|
||||||
<input class="text-neutral-200 p-2 bg-transparent input-text focus:bg-selected text-sm" bind:value={value.insertorder} type="number" min={0} max={1000}>
|
<input class="text-neutral-200 p-2 bg-transparent input-text focus:bg-selected text-sm" bind:value={value.insertorder} type="number" min={0} max={1000}>
|
||||||
<span class="text-neutral-200 mt-4">{language.prompt}</span>
|
<span class="text-neutral-200 mt-4">{language.prompt}</span>
|
||||||
<textarea class="bg-transparent input-text mt-2 text-gray-200 resize-none h-20 focus:bg-selected text-xs" autocomplete="off" bind:value={value.content}></textarea>
|
<textarea class="bg-transparent input-text mt-2 text-gray-200 resize-none h-20 focus:bg-selected text-xs" autocomplete="off" bind:value={value.content}></textarea>
|
||||||
<div class="flex items-center mt-4 mb-6">
|
<div class="flex items-center mt-4">
|
||||||
<Check bind:check={value.alwaysActive}/>
|
<Check bind:check={value.alwaysActive}/>
|
||||||
<span>{language.alwaysActive}</span>
|
<span>{language.alwaysActive}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center mt-2 mb-6">
|
||||||
|
<Check bind:check={value.selective}/>
|
||||||
|
<span>{language.selective} <Help key="loreSelective"/></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
import { language } from "../../lang";
|
import { language } from "../../lang";
|
||||||
import {selectedCharID} from '../../ts/stores'
|
import {selectedCharID} from '../../ts/stores'
|
||||||
import { DownloadIcon, FolderUpIcon, ImportIcon, PlusIcon } from "lucide-svelte";
|
import { DownloadIcon, FolderUpIcon, ImportIcon, PlusIcon } from "lucide-svelte";
|
||||||
import { addLorebook, exportLoreBook, importLoreBook } from "../../ts/lorebook";
|
import { addLorebook, exportLoreBook, importLoreBook } from "../../ts/process/lorebook";
|
||||||
import LoreBookData from "./LoreBookData.svelte";
|
import LoreBookData from "./LoreBookData.svelte";
|
||||||
|
import Check from "../Others/Check.svelte";
|
||||||
let submenu = 0
|
let submenu = 0
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -19,43 +20,77 @@
|
|||||||
}} class="flex-1 border-solid border-borderc border-1 border-l-transparent p-2 flex justify-center cursor-pointer" class:bg-selected={submenu === 1}>
|
}} class="flex-1 border-solid border-borderc border-1 border-l-transparent p-2 flex justify-center cursor-pointer" class:bg-selected={submenu === 1}>
|
||||||
<span>{language.Chat}</span>
|
<span>{language.Chat}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button on:click={() => {
|
||||||
|
submenu = 2
|
||||||
|
}} class="flex-1 border-solid border-borderc border-1 border-l-transparent p-2 flex justify-center cursor-pointer" class:bg-selected={submenu === 2}>
|
||||||
|
<span>{language.settings}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-gray-500 mt-2 mb-6 text-sm">{submenu === 0 ? $DataBase.characters[$selectedCharID].type === 'group' ? language.groupLoreInfo : language.globalLoreInfo : language.localLoreInfo}</span>
|
{#if submenu !== 2}
|
||||||
|
<span class="text-gray-500 mt-2 mb-6 text-sm">{submenu === 0 ? $DataBase.characters[$selectedCharID].type === 'group' ? language.groupLoreInfo : language.globalLoreInfo : language.localLoreInfo}</span>
|
||||||
<div class="border-solid border-borderc p-2 flex flex-col border-1">
|
<div class="border-solid border-borderc p-2 flex flex-col border-1">
|
||||||
{#if submenu === 0}
|
{#if submenu === 0}
|
||||||
{#if $DataBase.characters[$selectedCharID].globalLore.length === 0}
|
{#if $DataBase.characters[$selectedCharID].globalLore.length === 0}
|
||||||
<span class="text-gray-500">No Lorebook</span>
|
<span class="text-gray-500">No Lorebook</span>
|
||||||
{:else}
|
{:else}
|
||||||
{#each $DataBase.characters[$selectedCharID].globalLore as book, i}
|
{#each $DataBase.characters[$selectedCharID].globalLore as book, i}
|
||||||
{#if i !== 0}
|
{#if i !== 0}
|
||||||
<div class="border-borderc mt-2 mb-2 w-full border-solid border-b-1 seperator"></div>
|
<div class="border-borderc mt-2 mb-2 w-full border-solid border-b-1 seperator"></div>
|
||||||
{/if}
|
{/if}
|
||||||
<LoreBookData bind:value={$DataBase.characters[$selectedCharID].globalLore[i]} onRemove={() => {
|
<LoreBookData bind:value={$DataBase.characters[$selectedCharID].globalLore[i]} onRemove={() => {
|
||||||
let lore = $DataBase.characters[$selectedCharID].globalLore
|
let lore = $DataBase.characters[$selectedCharID].globalLore
|
||||||
lore.splice(i, 1)
|
lore.splice(i, 1)
|
||||||
$DataBase.characters[$selectedCharID].globalLore = lore
|
$DataBase.characters[$selectedCharID].globalLore = lore
|
||||||
}}/>
|
}}/>
|
||||||
{/each}
|
{/each}
|
||||||
|
{/if}
|
||||||
|
{:else if submenu === 1}
|
||||||
|
{#if $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore.length === 0}
|
||||||
|
<span class="text-gray-500">No Lorebook</span>
|
||||||
|
{:else}
|
||||||
|
{#each $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore as book, i}
|
||||||
|
{#if i !== 0}
|
||||||
|
<div class="border-borderc mt-2 mb-2 w-full border-solid border-b-1 seperator"></div>
|
||||||
|
{/if}
|
||||||
|
<LoreBookData bind:value={$DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore[i]} onRemove={() => {
|
||||||
|
let lore = $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore
|
||||||
|
lore.splice(i, 1)
|
||||||
|
$DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore = lore
|
||||||
|
}}/>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
{#if $DataBase.characters[$selectedCharID].loreSettings}
|
||||||
|
<div class="flex items-center mt-4">
|
||||||
|
<Check check={false} onChange={() => {
|
||||||
|
$DataBase.characters[$selectedCharID].loreSettings = undefined
|
||||||
|
}}/>
|
||||||
|
<span>{language.useGlobalSettings}</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mt-4">
|
||||||
|
<Check bind:check={$DataBase.characters[$selectedCharID].loreSettings.recursiveScanning}/>
|
||||||
|
<span>{language.recursiveScanning}</span>
|
||||||
|
</div>
|
||||||
|
<span class="text-neutral-200 mt-4 mb-2">{language.loreBookDepth}</span>
|
||||||
|
<input class="text-neutral-200 mb-4 p-2 bg-transparent input-text focus:bg-selected text-sm" type="number" min={0} max="20" bind:value={$DataBase.characters[$selectedCharID].loreSettings.scanDepth}>
|
||||||
|
<span class="text-neutral-200">{language.loreBookToken}</span>
|
||||||
|
<input class="text-neutral-200 mb-4 p-2 bg-transparent input-text focus:bg-selected text-sm" type="number" min={0} max="4096" bind:value={$DataBase.characters[$selectedCharID].loreSettings.tokenBudget}>
|
||||||
{:else}
|
{:else}
|
||||||
{#if $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore.length === 0}
|
<div class="flex items-center mt-4">
|
||||||
<span class="text-gray-500">No Lorebook</span>
|
<Check check={true} onChange={() => {
|
||||||
{:else}
|
$DataBase.characters[$selectedCharID].loreSettings = {
|
||||||
{#each $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore as book, i}
|
tokenBudget: $DataBase.loreBookToken,
|
||||||
{#if i !== 0}
|
scanDepth:$DataBase.loreBookDepth,
|
||||||
<div class="border-borderc mt-2 mb-2 w-full border-solid border-b-1 seperator"></div>
|
recursiveScanning: false
|
||||||
{/if}
|
}
|
||||||
<LoreBookData bind:value={$DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore[i]} onRemove={() => {
|
}}/>
|
||||||
let lore = $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore
|
<span>{language.useGlobalSettings}</span>
|
||||||
lore.splice(i, 1)
|
</div>
|
||||||
$DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].localLore = lore
|
|
||||||
}}/>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
{/if}
|
||||||
</div>
|
{#if submenu !== 2}
|
||||||
|
|
||||||
<div class="text-gray-500 mt-2 flex">
|
<div class="text-gray-500 mt-2 flex">
|
||||||
<button on:click={() => {addLorebook(submenu)}} class="hover:text-neutral-200 cursor-pointer">
|
<button on:click={() => {addLorebook(submenu)}} class="hover:text-neutral-200 cursor-pointer">
|
||||||
@@ -72,7 +107,7 @@
|
|||||||
<FolderUpIcon />
|
<FolderUpIcon />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
<style>
|
<style>
|
||||||
.seperator{
|
.seperator{
|
||||||
border-top: 0px;
|
border-top: 0px;
|
||||||
|
|||||||
@@ -499,7 +499,10 @@
|
|||||||
<Check bind:check={$DataBase.useSayNothing}/>
|
<Check bind:check={$DataBase.useSayNothing}/>
|
||||||
<span>{language.sayNothing}</span>
|
<span>{language.sayNothing}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center mt-4">
|
||||||
|
<Check bind:check={$DataBase.showUnrecommended}/>
|
||||||
|
<span>{language.showUnrecommended}</span>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
alertMd(getRequestLog())
|
alertMd(getRequestLog())
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ html, body{
|
|||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 5px;
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Track */
|
/* Track */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { get } from "svelte/store"
|
import { get } from "svelte/store"
|
||||||
import { alertConfirm, alertError, alertNormal, alertStore } from "./alert"
|
import { alertConfirm, alertError, alertNormal, alertSelect, alertStore } from "./alert"
|
||||||
import { DataBase, defaultSdDataFunc, type character, saveImage, setDatabase, type customscript } from "./database"
|
import { DataBase, defaultSdDataFunc, type character, saveImage, setDatabase, type customscript, type loreSettings, type loreBook } from "./database"
|
||||||
import { checkNullish, selectSingleFile, sleep } from "./util"
|
import { checkNullish, selectSingleFile, sleep } from "./util"
|
||||||
import { language } from "src/lang"
|
import { language } from "src/lang"
|
||||||
import { encode as encodeMsgpack, decode as decodeMsgpack } from "@msgpack/msgpack";
|
import { encode as encodeMsgpack, decode as decodeMsgpack } from "@msgpack/msgpack";
|
||||||
@@ -11,7 +11,6 @@ import { characterFormatUpdate } from "./characters"
|
|||||||
import { downloadFile, readImage } from "./globalApi"
|
import { downloadFile, readImage } from "./globalApi"
|
||||||
import { cloneDeep } from "lodash"
|
import { cloneDeep } from "lodash"
|
||||||
|
|
||||||
type CharacterBook = null
|
|
||||||
|
|
||||||
export async function importCharacter() {
|
export async function importCharacter() {
|
||||||
try {
|
try {
|
||||||
@@ -160,20 +159,11 @@ export async function characterHubImport() {
|
|||||||
|
|
||||||
function convertOldTavernAndJSON(charaData:OldTavernChar, imgp:string|undefined = undefined):character{
|
function convertOldTavernAndJSON(charaData:OldTavernChar, imgp:string|undefined = undefined):character{
|
||||||
|
|
||||||
let desc = charaData.description ?? ''
|
|
||||||
|
|
||||||
if(charaData.personality){
|
|
||||||
desc += '\n\n' + charaData.personality
|
|
||||||
}
|
|
||||||
|
|
||||||
if(charaData.scenario){
|
|
||||||
desc += '\n\n' + charaData.scenario
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: charaData.name ?? 'unknown name',
|
name: charaData.name ?? 'unknown name',
|
||||||
firstMessage: charaData.first_mes ?? 'unknown first message',
|
firstMessage: charaData.first_mes ?? 'unknown first message',
|
||||||
desc: desc,
|
desc: charaData.description ?? '',
|
||||||
notes: '',
|
notes: '',
|
||||||
chats: [{
|
chats: [{
|
||||||
message: [],
|
message: [],
|
||||||
@@ -191,13 +181,27 @@ function convertOldTavernAndJSON(charaData:OldTavernChar, imgp:string|undefined
|
|||||||
sdData: defaultSdDataFunc(),
|
sdData: defaultSdDataFunc(),
|
||||||
utilityBot: false,
|
utilityBot: false,
|
||||||
customscript: [],
|
customscript: [],
|
||||||
exampleMessage: charaData.mes_example
|
exampleMessage: charaData.mes_example,
|
||||||
|
creatorNotes:'',
|
||||||
|
systemPrompt:'',
|
||||||
|
postHistoryInstructions:'',
|
||||||
|
alternateGreetings:[],
|
||||||
|
tags:[],
|
||||||
|
creator:"",
|
||||||
|
characterVersion: 0,
|
||||||
|
personality: charaData.personality ?? '',
|
||||||
|
scenario:charaData.scenario ?? '',
|
||||||
|
firstMsgIndex: -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function exportChar(charaID:number) {
|
export async function exportChar(charaID:number) {
|
||||||
const db = get(DataBase)
|
const db = get(DataBase)
|
||||||
let char:character = JSON.parse(JSON.stringify(db.characters[charaID]))
|
let char = cloneDeep(db.characters[charaID])
|
||||||
|
|
||||||
|
if(char.type === 'group'){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if(!char.image){
|
if(!char.image){
|
||||||
alertError('Image Required')
|
alertError('Image Required')
|
||||||
@@ -208,6 +212,12 @@ export async function exportChar(charaID:number) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sel = await alertSelect(['Export as Spec V2','Export as Old RisuCard'])
|
||||||
|
if(sel === '0'){
|
||||||
|
exportSpecV2(char)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
alertStore.set({
|
alertStore.set({
|
||||||
type: 'wait',
|
type: 'wait',
|
||||||
msg: 'Loading...'
|
msg: 'Loading...'
|
||||||
@@ -288,6 +298,7 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array):Promise<boole
|
|||||||
if(!card ||card.spec !== 'chara_card_v2'){
|
if(!card ||card.spec !== 'chara_card_v2'){
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = card.data
|
const data = card.data
|
||||||
const im = img ? await saveImage(PngMetadata.filter(img)) : undefined
|
const im = img ? await saveImage(PngMetadata.filter(img)) : undefined
|
||||||
let db = get(DataBase)
|
let db = get(DataBase)
|
||||||
@@ -319,11 +330,45 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array):Promise<boole
|
|||||||
sdData = risuext.sdData ?? sdData
|
sdData = risuext.sdData ?? sdData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const charbook = data.character_book
|
||||||
|
let lorebook:loreBook[] = []
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let char:character = {
|
let char:character = {
|
||||||
name: data.name,
|
name: data.name ?? '',
|
||||||
firstMessage: data.first_mes,
|
firstMessage: data.first_mes ?? '',
|
||||||
desc: data.description,
|
desc: data.description ?? '',
|
||||||
notes: data.post_history_instructions,
|
notes: '',
|
||||||
chats: [{
|
chats: [{
|
||||||
message: [],
|
message: [],
|
||||||
note: '',
|
note: '',
|
||||||
@@ -334,15 +379,34 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array):Promise<boole
|
|||||||
image: im,
|
image: im,
|
||||||
emotionImages: emotions,
|
emotionImages: emotions,
|
||||||
bias: bias,
|
bias: bias,
|
||||||
globalLore: [], //lorebook
|
globalLore: lorebook, //lorebook
|
||||||
viewScreen: viewScreen,
|
viewScreen: viewScreen,
|
||||||
chaId: uuidv4(),
|
chaId: uuidv4(),
|
||||||
sdData: sdData,
|
sdData: sdData,
|
||||||
utilityBot: utilityBot,
|
utilityBot: utilityBot,
|
||||||
customscript: customScripts,
|
customscript: customScripts,
|
||||||
exampleMessage: data.mes_example
|
exampleMessage: data.mes_example ?? '',
|
||||||
|
creatorNotes:data.creator_notes ?? '',
|
||||||
|
systemPrompt:data.system_prompt ?? '',
|
||||||
|
postHistoryInstructions:data.post_history_instructions ?? '',
|
||||||
|
alternateGreetings:data.alternate_greetings ?? [],
|
||||||
|
tags:data.tags ?? [],
|
||||||
|
creator:data.creator ?? '',
|
||||||
|
characterVersion: data.character_version ?? 0,
|
||||||
|
personality:data.personality ?? '',
|
||||||
|
scenario:data.scenario ?? '',
|
||||||
|
firstMsgIndex: -1,
|
||||||
|
removedQuotes: false,
|
||||||
|
loreSettings: loresettings,
|
||||||
|
loreExt: loreExt,
|
||||||
|
additionalData: {
|
||||||
|
tag: data.tags,
|
||||||
|
creator: data.creator,
|
||||||
|
character_version: data.character_version
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.characters.push(char)
|
||||||
|
|
||||||
setDatabase(db)
|
setDatabase(db)
|
||||||
|
|
||||||
@@ -351,6 +415,103 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array):Promise<boole
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function exportSpecV2(char:character) {
|
||||||
|
let img = await readImage(char.image)
|
||||||
|
|
||||||
|
try{
|
||||||
|
|
||||||
|
let charBook:charBookEntry[] = []
|
||||||
|
for(const lore of char.globalLore){
|
||||||
|
charBook.push({
|
||||||
|
keys: lore.key.split(',').map(r => r.trim()),
|
||||||
|
secondary_keys: lore.selective ? lore.secondkey.split(',').map(r => r.trim()) : undefined,
|
||||||
|
content: lore.content,
|
||||||
|
extensions: lore.extentions ?? {},
|
||||||
|
enabled: true,
|
||||||
|
insertion_order: lore.insertorder,
|
||||||
|
constant: lore.alwaysActive,
|
||||||
|
selective:lore.selective,
|
||||||
|
name: lore.comment,
|
||||||
|
comment: lore.comment
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const card:CharacterCardV2 = {
|
||||||
|
spec: "chara_card_v2",
|
||||||
|
spec_version: "2.0",
|
||||||
|
data: {
|
||||||
|
name: char.name,
|
||||||
|
description: char.desc,
|
||||||
|
personality: char.personality,
|
||||||
|
scenario: char.scenario,
|
||||||
|
first_mes: char.firstMessage,
|
||||||
|
mes_example: char.exampleMessage,
|
||||||
|
creator_notes: char.creatorNotes,
|
||||||
|
system_prompt: char.systemPrompt,
|
||||||
|
post_history_instructions: char.postHistoryInstructions,
|
||||||
|
alternate_greetings: char.alternateGreetings,
|
||||||
|
character_book: {
|
||||||
|
scan_depth: char.loreSettings?.scanDepth,
|
||||||
|
token_budget: char.loreSettings?.tokenBudget,
|
||||||
|
recursive_scanning: char.loreSettings?.recursiveScanning,
|
||||||
|
extensions: char.loreExt ?? {},
|
||||||
|
entries: []
|
||||||
|
},
|
||||||
|
tags: char.additionalData?.tag ?? [],
|
||||||
|
creator: char.additionalData?.creator ?? '',
|
||||||
|
character_version: char.additionalData?.character_version ?? 0,
|
||||||
|
extensions: {
|
||||||
|
risuai: {
|
||||||
|
emotions: char.emotionImages,
|
||||||
|
bias: char.bias,
|
||||||
|
viewScreen: char.viewScreen,
|
||||||
|
customScripts: char.customscript,
|
||||||
|
utilityBot: char.utilityBot,
|
||||||
|
sdData: char.sdData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(card.data.extensions.risuai.emotions && card.data.extensions.risuai.emotions.length > 0){
|
||||||
|
for(let i=0;i<card.data.extensions.risuai.emotions.length;i++){
|
||||||
|
alertStore.set({
|
||||||
|
type: 'wait',
|
||||||
|
msg: `Loading... (Getting Emotions ${i} / ${card.data.extensions.risuai.emotions.length})`
|
||||||
|
})
|
||||||
|
const rData = await readImage(card.data.extensions.risuai.emotions[i][1])
|
||||||
|
char.emotionImages[i][1] = Buffer.from(rData).toString('base64')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alertStore.set({
|
||||||
|
type: 'wait',
|
||||||
|
msg: 'Loading... (Writing Exif)'
|
||||||
|
})
|
||||||
|
|
||||||
|
await sleep(10)
|
||||||
|
img = PngMetadata.write(img, {
|
||||||
|
'chara': Buffer.from(JSON.stringify(card)).toString('base64'),
|
||||||
|
})
|
||||||
|
|
||||||
|
alertStore.set({
|
||||||
|
type: 'wait',
|
||||||
|
msg: 'Loading... (Writing)'
|
||||||
|
})
|
||||||
|
|
||||||
|
char.image = ''
|
||||||
|
await sleep(10)
|
||||||
|
await downloadFile(`${char.name.replace(/[<>:"/\\|?*\.\,]/g, "")}_export.png`, img)
|
||||||
|
|
||||||
|
alertNormal(language.successExport)
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(e){
|
||||||
|
alertError(`${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type CharacterCardV2 = {
|
type CharacterCardV2 = {
|
||||||
spec: 'chara_card_v2'
|
spec: 'chara_card_v2'
|
||||||
@@ -396,3 +557,33 @@ interface OldTavernChar{
|
|||||||
scenario: ""
|
scenario: ""
|
||||||
talkativeness: "0.5"
|
talkativeness: "0.5"
|
||||||
}
|
}
|
||||||
|
type CharacterBook = {
|
||||||
|
name?: string
|
||||||
|
description?: string
|
||||||
|
scan_depth?: number // agnai: "Memory: Chat History Depth"
|
||||||
|
token_budget?: number // agnai: "Memory: Context Limit"
|
||||||
|
recursive_scanning?: boolean // no agnai equivalent. whether entry content can trigger other entries
|
||||||
|
extensions: Record<string, any>
|
||||||
|
entries: Array<charBookEntry>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface charBookEntry{
|
||||||
|
keys: Array<string>
|
||||||
|
content: string
|
||||||
|
extensions: Record<string, any>
|
||||||
|
enabled: boolean
|
||||||
|
insertion_order: number // if two entries inserted, lower "insertion order" = inserted higher
|
||||||
|
|
||||||
|
// FIELDS WITH NO CURRENT EQUIVALENT IN SILLY
|
||||||
|
name?: string // not used in prompt engineering
|
||||||
|
priority?: number // if token budget reached, lower priority value = discarded first
|
||||||
|
|
||||||
|
// FIELDS WITH NO CURRENT EQUIVALENT IN AGNAI
|
||||||
|
id?: number // not used in prompt engineering
|
||||||
|
comment?: string // not used in prompt engineering
|
||||||
|
selective?: boolean // if `true`, require a key from both `keys` and `secondary_keys` to trigger the entry
|
||||||
|
secondary_keys?: Array<string> // see field `selective`. ignored if selective == false
|
||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
@@ -37,6 +37,7 @@ export function createNewGroup(){
|
|||||||
emotionImages: [],
|
emotionImages: [],
|
||||||
customscript: [],
|
customscript: [],
|
||||||
chaId: uuidv4(),
|
chaId: uuidv4(),
|
||||||
|
firstMsgIndex: -1
|
||||||
})
|
})
|
||||||
setDatabase(db)
|
setDatabase(db)
|
||||||
return db.characters.length - 1
|
return db.characters.length - 1
|
||||||
@@ -269,6 +270,18 @@ export function characterFormatUpdate(index:number|character){
|
|||||||
if(checkNullish(cha.utilityBot)){
|
if(checkNullish(cha.utilityBot)){
|
||||||
cha.utilityBot = false
|
cha.utilityBot = false
|
||||||
}
|
}
|
||||||
|
cha.alternateGreetings = cha.alternateGreetings ?? []
|
||||||
|
cha.exampleMessage = cha.exampleMessage ?? ''
|
||||||
|
cha.creatorNotes = cha.creatorNotes ?? ''
|
||||||
|
cha.systemPrompt = cha.systemPrompt ?? ''
|
||||||
|
cha.postHistoryInstructions = cha.postHistoryInstructions ?? ''
|
||||||
|
cha.tags = cha.tags ?? []
|
||||||
|
cha.creator = cha.creator ?? ''
|
||||||
|
cha.characterVersion = cha.characterVersion ?? 0
|
||||||
|
cha.personality = cha.personality ?? ''
|
||||||
|
cha.scenario = cha.scenario ?? ''
|
||||||
|
cha.firstMsgIndex = cha.firstMsgIndex ?? -1
|
||||||
|
|
||||||
}
|
}
|
||||||
if(checkNullish(cha.customscript)){
|
if(checkNullish(cha.customscript)){
|
||||||
cha.customscript = []
|
cha.customscript = []
|
||||||
@@ -303,7 +316,17 @@ export function createBlankChar():character{
|
|||||||
sdData: defaultSdDataFunc(),
|
sdData: defaultSdDataFunc(),
|
||||||
utilityBot: false,
|
utilityBot: false,
|
||||||
customscript: [],
|
customscript: [],
|
||||||
exampleMessage: ''
|
exampleMessage: '',
|
||||||
|
creatorNotes:'',
|
||||||
|
systemPrompt:'',
|
||||||
|
postHistoryInstructions:'',
|
||||||
|
alternateGreetings:[],
|
||||||
|
tags:[],
|
||||||
|
creator:"",
|
||||||
|
characterVersion: 0,
|
||||||
|
personality:"",
|
||||||
|
scenario:"",
|
||||||
|
firstMsgIndex: -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { cloneDeep } from 'lodash';
|
|||||||
|
|
||||||
export const DataBase = writable({} as any as Database)
|
export const DataBase = writable({} as any as Database)
|
||||||
export const loadedStore = writable(false)
|
export const loadedStore = writable(false)
|
||||||
export let appVer = '0.7.9'
|
export let appVer = '0.8.0'
|
||||||
|
|
||||||
|
|
||||||
export function setDatabase(data:Database){
|
export function setDatabase(data:Database){
|
||||||
@@ -178,6 +178,9 @@ export function setDatabase(data:Database){
|
|||||||
if(checkNullish(data.requestproxy)){
|
if(checkNullish(data.requestproxy)){
|
||||||
data.requestproxy = ''
|
data.requestproxy = ''
|
||||||
}
|
}
|
||||||
|
if(checkNullish(data.showUnrecommended)){
|
||||||
|
data.showUnrecommended = false
|
||||||
|
}
|
||||||
if(checkNullish(data.sdConfig)){
|
if(checkNullish(data.sdConfig)){
|
||||||
data.sdConfig = {
|
data.sdConfig = {
|
||||||
width:512,
|
width:512,
|
||||||
@@ -213,11 +216,14 @@ export interface customscript{
|
|||||||
|
|
||||||
export interface loreBook{
|
export interface loreBook{
|
||||||
key:string
|
key:string
|
||||||
|
secondkey:string
|
||||||
insertorder: number
|
insertorder: number
|
||||||
comment: string
|
comment: string
|
||||||
content: string
|
content: string
|
||||||
mode: 'multiple'|'constant'|'normal',
|
mode: 'multiple'|'constant'|'normal',
|
||||||
alwaysActive: boolean
|
alwaysActive: boolean
|
||||||
|
selective:boolean
|
||||||
|
extentions?:{}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface character{
|
export interface character{
|
||||||
@@ -238,8 +244,34 @@ export interface character{
|
|||||||
customscript: customscript[]
|
customscript: customscript[]
|
||||||
utilityBot: boolean
|
utilityBot: boolean
|
||||||
exampleMessage:string
|
exampleMessage:string
|
||||||
|
removedQuotes?:boolean
|
||||||
|
creatorNotes:string
|
||||||
|
systemPrompt:string
|
||||||
|
postHistoryInstructions:string
|
||||||
|
alternateGreetings:string[]
|
||||||
|
tags:string[]
|
||||||
|
creator:string
|
||||||
|
characterVersion: number
|
||||||
|
personality:string
|
||||||
|
scenario:string
|
||||||
|
firstMsgIndex:number
|
||||||
|
loreSettings?:loreSettings
|
||||||
|
loreExt?:any
|
||||||
|
additionalData?: {
|
||||||
|
tag?:string[]
|
||||||
|
creator?:string
|
||||||
|
character_version?:number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface loreSettings{
|
||||||
|
tokenBudget: number
|
||||||
|
scanDepth:number
|
||||||
|
recursiveScanning: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface groupChat{
|
export interface groupChat{
|
||||||
type: 'group'
|
type: 'group'
|
||||||
image?:string
|
image?:string
|
||||||
@@ -255,6 +287,11 @@ export interface groupChat{
|
|||||||
emotionImages: [string, string][]
|
emotionImages: [string, string][]
|
||||||
customscript: customscript[],
|
customscript: customscript[],
|
||||||
chaId: string
|
chaId: string
|
||||||
|
alternateGreetings?: string[]
|
||||||
|
creatorNotes?:string,
|
||||||
|
removedQuotes?:boolean
|
||||||
|
firstMsgIndex?:number,
|
||||||
|
loreSettings?:loreSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface botPreset{
|
export interface botPreset{
|
||||||
@@ -348,6 +385,7 @@ export interface Database{
|
|||||||
didFirstSetup: boolean
|
didFirstSetup: boolean
|
||||||
requestmet: string
|
requestmet: string
|
||||||
requestproxy: string
|
requestproxy: string
|
||||||
|
showUnrecommended:boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
62
src/ts/process/exampleMessages.ts
Normal file
62
src/ts/process/exampleMessages.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import type { OpenAIChat } from ".";
|
||||||
|
import type { character } from "../database";
|
||||||
|
import { replacePlaceholders } from "../util";
|
||||||
|
|
||||||
|
export function exampleMessage(char:character):OpenAIChat[]{
|
||||||
|
if(char.exampleMessage === ''){
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const messages = char.exampleMessage.split('\n')
|
||||||
|
let result:OpenAIChat[] = []
|
||||||
|
let currentMessage:OpenAIChat
|
||||||
|
|
||||||
|
function add(){
|
||||||
|
if(currentMessage){
|
||||||
|
result.push(currentMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const mes of messages){
|
||||||
|
const trimed = mes.trim()
|
||||||
|
const lowered = trimed.toLocaleLowerCase()
|
||||||
|
|
||||||
|
|
||||||
|
if(lowered === '<start>'){
|
||||||
|
add()
|
||||||
|
result.push({
|
||||||
|
role: "system",
|
||||||
|
content: '[Start a new chat]'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if(lowered.startsWith('{{char}}:') || lowered.startsWith('<bot>:') || lowered.startsWith(`${char.name}:`)){
|
||||||
|
add()
|
||||||
|
currentMessage = {
|
||||||
|
role: "assistant",
|
||||||
|
content: trimed.split(':', 2)[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(lowered.startsWith('{{user}}:') || lowered.startsWith('<user>:')){
|
||||||
|
add()
|
||||||
|
currentMessage = {
|
||||||
|
role: "user",
|
||||||
|
content: trimed.split(':', 2)[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(currentMessage){
|
||||||
|
currentMessage.content += "\n" + trimed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add()
|
||||||
|
|
||||||
|
result = result.map((r) => {
|
||||||
|
return {
|
||||||
|
role: r.role,
|
||||||
|
content: replacePlaceholders(r.content, char.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -4,11 +4,12 @@ import { CharEmotion, selectedCharID } from "../stores";
|
|||||||
import { tokenize, tokenizeNum } from "../tokenizer";
|
import { tokenize, tokenizeNum } from "../tokenizer";
|
||||||
import { language } from "../../lang";
|
import { language } from "../../lang";
|
||||||
import { alertError } from "../alert";
|
import { alertError } from "../alert";
|
||||||
import { loadLoreBookPrompt } from "../lorebook";
|
import { loadLoreBookPrompt } from "./lorebook";
|
||||||
import { findCharacterbyId, replacePlaceholders } from "../util";
|
import { findCharacterbyId, replacePlaceholders } from "../util";
|
||||||
import { requestChatData } from "./request";
|
import { requestChatData } from "./request";
|
||||||
import { stableDiff } from "./stableDiff";
|
import { stableDiff } from "./stableDiff";
|
||||||
import { processScript, processScriptFull } from "./scripts";
|
import { processScript, processScriptFull } from "./scripts";
|
||||||
|
import { exampleMessage } from "./exampleMessages";
|
||||||
|
|
||||||
export interface OpenAIChat{
|
export interface OpenAIChat{
|
||||||
role: 'system'|'user'|'assistant'
|
role: 'system'|'user'|'assistant'
|
||||||
@@ -99,9 +100,11 @@ export async function sendChat(chatProcessIndex = -1):Promise<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!currentChar.utilityBot){
|
if(!currentChar.utilityBot){
|
||||||
|
const mainp = currentChar.systemPrompt.length > 3 ? currentChar.systemPrompt : db.mainPrompt
|
||||||
|
|
||||||
unformated.main.push({
|
unformated.main.push({
|
||||||
role: 'system',
|
role: 'system',
|
||||||
content: replacePlaceholders(db.mainPrompt + ((db.additionalPrompt === '' || (!db.promptPreprocess)) ? '' : `\n${db.additionalPrompt}`), currentChar.name)
|
content: replacePlaceholders(mainp + ((db.additionalPrompt === '' || (!db.promptPreprocess)) ? '' : `\n${db.additionalPrompt}`), currentChar.name)
|
||||||
})
|
})
|
||||||
|
|
||||||
if(db.jailbreakToggle){
|
if(db.jailbreakToggle){
|
||||||
@@ -122,10 +125,30 @@ export async function sendChat(chatProcessIndex = -1):Promise<boolean> {
|
|||||||
content: replacePlaceholders(currentChat.note, currentChar.name)
|
content: replacePlaceholders(currentChat.note, currentChar.name)
|
||||||
})
|
})
|
||||||
|
|
||||||
unformated.description.push({
|
if(currentChar.postHistoryInstructions !== ''){
|
||||||
role: 'system',
|
unformated.authorNote.push({
|
||||||
content: replacePlaceholders((db.promptPreprocess ? db.descriptionPrefix: '') + currentChar.desc, currentChar.name)
|
role: 'system',
|
||||||
})
|
content: replacePlaceholders(currentChar.postHistoryInstructions, currentChar.name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let description = replacePlaceholders((db.promptPreprocess ? db.descriptionPrefix: '') + currentChar.desc, currentChar.name)
|
||||||
|
|
||||||
|
if(currentChar.personality){
|
||||||
|
description += replacePlaceholders("\n\nDescription of {{char}}: " + currentChar.personality,currentChar.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(currentChar.scenario){
|
||||||
|
description += replacePlaceholders("\n\nCircumstances and context of the dialogue: " + currentChar.scenario,currentChar.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
unformated.description.push({
|
||||||
|
role: 'system',
|
||||||
|
content: description
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
unformated.lorebook.push({
|
unformated.lorebook.push({
|
||||||
role: 'system',
|
role: 'system',
|
||||||
@@ -139,20 +162,12 @@ export async function sendChat(chatProcessIndex = -1):Promise<boolean> {
|
|||||||
}).join('\n\n')
|
}).join('\n\n')
|
||||||
}).join('\n\n')) + db.maxResponse) + 150
|
}).join('\n\n')) + db.maxResponse) + 150
|
||||||
|
|
||||||
let chats:OpenAIChat[] = []
|
let chats:OpenAIChat[] = exampleMessage(currentChar)
|
||||||
|
|
||||||
if(nowChatroom.type === 'group'){
|
chats.push({
|
||||||
chats.push({
|
role: 'system',
|
||||||
role: 'system',
|
content: '[Start a new chat]'
|
||||||
content: '[Start a new group chat]'
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
chats.push({
|
|
||||||
role: 'system',
|
|
||||||
content: '[Start a new chat]'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
chats.push({
|
chats.push({
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
@@ -349,25 +364,6 @@ export async function sendChat(chatProcessIndex = -1):Promise<boolean> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// const promptbody:OpenAIChat[] = [
|
|
||||||
// {
|
|
||||||
|
|
||||||
// role:'system',
|
|
||||||
// content: `assistant is a emotion extractor. user will input a prompt of a character, and assistant must output the emotion of a character.\n\n must chosen from this list: ${shuffleArray(emotionList).join(', ')} \noutput only one word.`
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// role: 'user',
|
|
||||||
// content: `"Good morning, Master! Is there anything I can do for you today?"`
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// role: 'assistant',
|
|
||||||
// content: 'happy'
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// role: 'user',
|
|
||||||
// content: result
|
|
||||||
// },
|
|
||||||
// ]
|
|
||||||
|
|
||||||
const promptbody:OpenAIChat[] = [
|
const promptbody:OpenAIChat[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import {selectedCharID} from './stores'
|
import {selectedCharID} from '../stores'
|
||||||
import { DataBase, setDatabase, type loreBook } from "./database";
|
import { DataBase, setDatabase, type loreBook } from "../database";
|
||||||
import { tokenize } from "./tokenizer";
|
import { tokenize } from "../tokenizer";
|
||||||
import { selectSingleFile } from "./util";
|
import { selectSingleFile } from "../util";
|
||||||
import { alertError, alertNormal } from "./alert";
|
import { alertError, alertNormal } from "../alert";
|
||||||
import { language } from "../lang";
|
import { language } from "../../lang";
|
||||||
import { downloadFile } from "./globalApi";
|
import { downloadFile } from "../globalApi";
|
||||||
|
|
||||||
export function addLorebook(type:number) {
|
export function addLorebook(type:number) {
|
||||||
let selectedID = get(selectedCharID)
|
let selectedID = get(selectedCharID)
|
||||||
@@ -17,7 +17,9 @@ export function addLorebook(type:number) {
|
|||||||
content: '',
|
content: '',
|
||||||
mode: 'normal',
|
mode: 'normal',
|
||||||
insertorder: 100,
|
insertorder: 100,
|
||||||
alwaysActive: false
|
alwaysActive: false,
|
||||||
|
secondkey: "",
|
||||||
|
selective: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@@ -28,16 +30,20 @@ export function addLorebook(type:number) {
|
|||||||
content: '',
|
content: '',
|
||||||
mode: 'normal',
|
mode: 'normal',
|
||||||
insertorder: 100,
|
insertorder: 100,
|
||||||
alwaysActive: false
|
alwaysActive: false,
|
||||||
|
secondkey: "",
|
||||||
|
selective: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
setDatabase(db)
|
setDatabase(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface formatedLore{
|
interface formatedLore{
|
||||||
keys:string[]|'always'
|
keys:string[]|'always',
|
||||||
|
secondKey:string[]
|
||||||
content: string
|
content: string
|
||||||
order: number
|
order: number
|
||||||
|
activatied: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const rmRegex = / |\n/g
|
const rmRegex = / |\n/g
|
||||||
@@ -45,11 +51,14 @@ const rmRegex = / |\n/g
|
|||||||
export async function loadLoreBookPrompt(){
|
export async function loadLoreBookPrompt(){
|
||||||
const selectedID = get(selectedCharID)
|
const selectedID = get(selectedCharID)
|
||||||
const db = get(DataBase)
|
const db = get(DataBase)
|
||||||
const page = db.characters[selectedID].chatPage
|
const char = db.characters[selectedID]
|
||||||
const globalLore = db.characters[selectedID].globalLore
|
const page = char.chatPage
|
||||||
const charLore = db.characters[selectedID].chats[page].localLore
|
const globalLore = char.globalLore
|
||||||
|
const charLore = char.chats[page].localLore
|
||||||
const fullLore = globalLore.concat(charLore)
|
const fullLore = globalLore.concat(charLore)
|
||||||
const currentChat = db.characters[selectedID].chats[page].message
|
const currentChat = char.chats[page].message
|
||||||
|
const loreDepth = char.loreSettings?.scanDepth ?? db.loreBookDepth
|
||||||
|
const loreToken = char.loreSettings?.tokenBudget ?? db.loreBookToken
|
||||||
|
|
||||||
let activatiedPrompt: string[] = []
|
let activatiedPrompt: string[] = []
|
||||||
|
|
||||||
@@ -61,8 +70,12 @@ export async function loadLoreBookPrompt(){
|
|||||||
keys: lore.alwaysActive ? 'always' : lore.key.replace(rmRegex, '').toLocaleLowerCase().split(',').filter((a) => {
|
keys: lore.alwaysActive ? 'always' : lore.key.replace(rmRegex, '').toLocaleLowerCase().split(',').filter((a) => {
|
||||||
return a.length > 1
|
return a.length > 1
|
||||||
}),
|
}),
|
||||||
|
secondKey: lore.selective ? lore.secondkey.replace(rmRegex, '').toLocaleLowerCase().split(',').filter((a) => {
|
||||||
|
return a.length > 1
|
||||||
|
}) : [],
|
||||||
content: lore.content,
|
content: lore.content,
|
||||||
order: lore.insertorder
|
order: lore.insertorder,
|
||||||
|
activatied: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,26 +84,58 @@ export async function loadLoreBookPrompt(){
|
|||||||
return b.order - a.order
|
return b.order - a.order
|
||||||
})
|
})
|
||||||
|
|
||||||
const formatedChat = currentChat.slice(currentChat.length - db.loreBookDepth,currentChat.length).map((msg) => {
|
const formatedChat = currentChat.slice(currentChat.length - loreDepth,currentChat.length).map((msg) => {
|
||||||
return msg.data
|
return msg.data
|
||||||
}).join('||').replace(rmRegex,'').toLocaleLowerCase()
|
}).join('||').replace(rmRegex,'').toLocaleLowerCase()
|
||||||
|
|
||||||
for(const lore of formatedLore){
|
let loreListUpdated = true
|
||||||
const totalTokens = await tokenize(activatiedPrompt.concat([lore.content]).join('\n\n'))
|
|
||||||
if(totalTokens > db.loreBookToken){
|
while(loreListUpdated){
|
||||||
break
|
loreListUpdated = false
|
||||||
}
|
for(let i=0;i<formatedLore.length;i++){
|
||||||
|
const lore = formatedLore[i]
|
||||||
if(lore.keys === 'always'){
|
if(lore.activatied){
|
||||||
activatiedPrompt.push(lore.content)
|
continue
|
||||||
continue
|
}
|
||||||
}
|
const totalTokens = await tokenize(activatiedPrompt.concat([lore.content]).join('\n\n'))
|
||||||
|
if(totalTokens > loreToken){
|
||||||
for(const key of lore.keys){
|
|
||||||
if(formatedChat.includes(key)){
|
|
||||||
activatiedPrompt.push(lore.content)
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(lore.keys === 'always'){
|
||||||
|
activatiedPrompt.push(lore.content)
|
||||||
|
lore.activatied = true
|
||||||
|
loreListUpdated = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
let firstKeyActivation = false
|
||||||
|
for(const key of lore.keys){
|
||||||
|
if(formatedChat.includes(key)){
|
||||||
|
firstKeyActivation = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(firstKeyActivation){
|
||||||
|
if(lore.secondKey.length === 0){
|
||||||
|
activatiedPrompt.push(lore.content)
|
||||||
|
lore.activatied = true
|
||||||
|
loreListUpdated = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for(const key of lore.secondKey){
|
||||||
|
if(formatedChat.includes(key)){
|
||||||
|
activatiedPrompt.push(lore.content)
|
||||||
|
lore.activatied = true
|
||||||
|
loreListUpdated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!(char.loreSettings?.recursiveScanning)){
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +152,8 @@ export async function importLoreBook(mode:'global'|'local'){
|
|||||||
if(!lorebook){
|
if(!lorebook){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const importedlore = JSON.parse(Buffer.from(lorebook).toString('utf-8'))
|
const importedlore = JSON.parse(Buffer.from(lorebook).toString('utf-8'))
|
||||||
@@ -129,10 +176,12 @@ export async function importLoreBook(mode:'global'|'local'){
|
|||||||
lore.push({
|
lore.push({
|
||||||
key: currentLore.key.join(', '),
|
key: currentLore.key.join(', '),
|
||||||
insertorder: currentLore.order,
|
insertorder: currentLore.order,
|
||||||
comment: currentLore.comment.length < 1 ? 'Unnamed Imported Lore': currentLore.comment,
|
comment: currentLore.comment.length < 1 ? 'Unnamed Imported Lore' : currentLore.comment,
|
||||||
content: currentLore.content,
|
content: currentLore.content,
|
||||||
mode: "normal",
|
mode: "normal",
|
||||||
alwaysActive: currentLore.constant
|
alwaysActive: currentLore.constant,
|
||||||
|
secondkey: "",
|
||||||
|
selective: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,13 +20,17 @@ export default {
|
|||||||
},
|
},
|
||||||
maxWidth:{
|
maxWidth:{
|
||||||
'half': '50%',
|
'half': '50%',
|
||||||
|
'80p': '80%',
|
||||||
|
'80vw': '80vw',
|
||||||
'14': '3.5rem',
|
'14': '3.5rem',
|
||||||
|
'100vw': '100vw'
|
||||||
},
|
},
|
||||||
borderWidth: {
|
borderWidth: {
|
||||||
'1': '1px',
|
'1': '1px',
|
||||||
},
|
},
|
||||||
width: {
|
width: {
|
||||||
'2xl': '48rem',
|
'2xl': '48rem',
|
||||||
|
'3xl': '72rem',
|
||||||
},
|
},
|
||||||
minHeight:{
|
minHeight:{
|
||||||
'8': '2rem',
|
'8': '2rem',
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":"0.7.9"}
|
{"version":"0.8.0"}
|
||||||
Reference in New Issue
Block a user