[feat] automark plugin

This commit is contained in:
kwaroran
2023-06-24 18:18:08 +09:00
parent 7cd314e2a1
commit 6810020376
7 changed files with 62 additions and 6 deletions

View File

@@ -0,0 +1,56 @@
const reg:[RegExp,string][] = []
export function autoMarkPlugin(data:string){
if(reg.length === 0){
const pluginRegex = [
{
"in": "“|”",
"out": "\"",
"flag": "g"
},
{
"in": "|",
"out": "'",
"flag": "g"
},
{
"in": "^(?!\\d\\.)([\\wㄱ-ㅎ가-힣'])(?!.*[{<>}])|(?<=^\\[.*\\] *|^\\(.*\\) *)([\\wㄱ-ㅎ가-힣'])(?!.*[{<>}])",
"out": "<em>$1$2",
"flag": "gm"
},
{
"in": "(?<!^ +.*)(\".*|<em>.*)(?<!\")$",
"out": "$1</em>",
"flag": "gm"
},
{
"in": "(?<=<em>.*|^\".*)( +\"[\\S])|(?<=<em>.*|\" +.*)( *\\[)",
"out": "</em>$1$2",
"flag": "gm"
},
{
"in": "(?<=^\".*|<\\/em>.*)([\\S]\" +|[\\S]\"(?=[,.…ㄱ-ㅎ가-힣]))|(?<=<\\/em>.*)( *\\] *)",
"out": "$1$2<em>",
"flag": "gm"
},
{
"in": "(?<=<em>.*? +|\\[|\\[.* +|\\(|\\(.* +|\"|\".*? +)(?<!style=.*)(')|(?<=<em>)('[\\wㄱ-ㅎ가-힣])",
"out": "<strong><em>$1$2",
"flag": "gm"
},
{
"in": "(?<=<strong><em>')(.*?')(?= +.+?|[ㄱ-ㅎ가-힣?!:;,.…—-])|(?<=<strong><em>'.*)(')(?=<\\/em>|\")|(?<=\\(<strong><em>')(?=\\))",
"out": "$1$2</em></strong>",
"flag": "gm"
}
]
for(const r of pluginRegex){
reg.push([new RegExp(r.in, r.flag),r.out])
}
}
for(let i=0;i<reg.length;i++){
data = data.replace(reg[i][0], reg[i][1])
}
return data
}

322
src/ts/plugins/plugins.ts Normal file
View File

@@ -0,0 +1,322 @@
import { get, writable } from "svelte/store";
import { language } from "../../lang";
import { alertError } from "../alert";
import { DataBase } from "../storage/database";
import { checkNullish, selectSingleFile, sleep } from "../util";
import type { OpenAIChat } from "../process";
import { globalFetch } from "../storage/globalApi";
import { selectedCharID } from "../stores";
export const customProviderStore = writable([] as string[])
interface PluginRequest{
url: string
header?:{[key:string]:string}
body: any,
res: string
}
interface ProviderPlugin{
name:string
displayName?:string
script:string
arguments:{[key:string]:'int'|'string'|string[]}
realArg:{[key:string]:number|string}
}
export type RisuPlugin = ProviderPlugin
export async function importPlugin(){
try {
let db = get(DataBase)
const f = await selectSingleFile(['js'])
if(!f){
return
}
const jsFile = Buffer.from(f.data).toString('utf-8').replace(/^\uFEFF/gm, "");
const splitedJs = jsFile.split('\n')
let name = ''
let displayName:string = undefined
let arg:{[key:string]:'int'|'string'|string[]} = {}
let realArg:{[key:string]:number|string} = {}
for(const line of splitedJs){
if(line.startsWith('//@risu-name')){
const provied = line.slice(13)
if(provied === ''){
alertError('plugin name must be longer than "", did you put it correctly?')
return
}
name = provied.trim()
}
if(line.startsWith('//@risu-display-name')){
const provied = line.slice('//@risu-display-name'.length + 1)
if(provied === ''){
alertError('plugin display name must be longer than "", did you put it correctly?')
return
}
name = provied.trim()
}
if(line.startsWith('//@risu-arg')){
const provied = line.trim().split(' ')
if(provied.length < 3){
alertError('plugin argument is incorrect, did you put space in argument name?')
return
}
const provKey = provied[1]
if(provied[2] !== 'int' && provied[2] !== 'string'){
alertError(`plugin argument type is "${provied[2]}", which is an unknown type.`)
return
}
if(provied[2] === 'int'){
arg[provKey] = 'int'
realArg[provKey] = 0
}
else if(provied[2] === 'string'){
arg[provKey] = 'string'
realArg[provKey] = ''
}
}
}
if(name.length === 0){
alertError('plugin name not found, did you put it correctly?')
return
}
let pluginData:RisuPlugin = {
name: name,
script: jsFile,
realArg: realArg,
arguments: arg,
displayName: displayName
}
db.plugins.push(pluginData)
DataBase.set(db)
loadPlugins()
} catch (error) {
console.error(error)
alertError(language.errors.noData)
}
}
export function getCurrentPluginMax(prov:string){
return 12000
}
let pluginWorker:Worker = null
let providerRes:{success:boolean, content:string} = null
let translatorRes:{success:boolean, content:string} = null
function postMsgPluginWorker(type:string, body:any){
const bod = {
type: type,
body: body
}
pluginWorker.postMessage(bod)
}
let pluginTranslator = false
export async function loadPlugins() {
let db = get(DataBase)
if(pluginWorker){
pluginWorker.terminate()
pluginWorker = null
}
if(db.plugins.length > 0){
const da = await fetch("/pluginApi.js")
const pluginApiString = await da.text()
let pluginjs = `${pluginApiString}\n`
let pluginLoadedJs = ''
for(const plug of db.plugins){
pluginLoadedJs += `\n(() => {${plug.script}})();\n`
}
pluginjs = pluginjs.replace('//{{placeholder}}',pluginLoadedJs)
const blob = new Blob([pluginjs], {type: 'application/javascript'});
pluginWorker = new Worker(URL.createObjectURL(blob));
pluginWorker.addEventListener('message', async (msg) => {
const data:{type:string,body:any} = msg.data
switch(data.type){
case "addProvider":{
let provs = get(customProviderStore)
provs.push(data.body)
customProviderStore.set(provs)
console.log(provs)
break
}
case "resProvider":{
const provres:{success:boolean, content:string} = data.body
if(checkNullish(provres.success) || checkNullish(provres.content)){
providerRes = {
success: false,
content :"provider didn't respond 'success' or 'content' in response object"
}
}
else if(typeof(provres.content) !== 'string'){
providerRes = {
success: false,
content :"provider didn't respond 'content' in response object in string"
}
}
else{
providerRes = {
success: !!provres.success,
content: provres.content
}
}
break
}
case "resTrans":{
const provres:{success:boolean, content:string} = data.body
if(checkNullish(provres.success) || checkNullish(provres.content)){
translatorRes = {
success: false,
content :"plugin didn't respond 'success' or 'content' in response object"
}
}
else if(typeof(provres.content) !== 'string'){
translatorRes = {
success: false,
content :"plugin didn't respond 'content' in response object in string"
}
}
else{
translatorRes = {
success: !!provres.success,
content: provres.content
}
}
break
}
case "useTranslator": {
pluginTranslator = true
}
case "fetch": {
postMsgPluginWorker('fetchData',{
id: data.body.id,
data: await globalFetch(data.body.url, data.body.arg)
})
break
}
case "getArg":{
try {
const db = get(DataBase)
const arg:string[] = data.body.arg.split('::')
for(const plug of db.plugins){
if(arg[0] === plug.name){
postMsgPluginWorker('fetchData',{
id: data.body.id,
data: plug.realArg[arg[1]]
})
return
}
}
postMsgPluginWorker('fetchData',{
id: data.body.id,
data: null
})
} catch (error) {
postMsgPluginWorker('fetchData',{
id: data.body.id,
data: null
})
}
break
}
case "getChar":{
const db = get(DataBase)
const charid = get(selectedCharID)
const char = db.characters[charid]
postMsgPluginWorker('fetchData',{
id: data.body.id,
data: char
})
}
case "setChar":{
const db = get(DataBase)
const charid = get(selectedCharID)
db.characters[charid] = data.body
}
case "log":{
console.log(data.body)
break
}
}
})
}
}
export async function translatorPlugin(text:string, from:string, to:string) {
if(!pluginTranslator){
return false
}
else{
try {
translatorRes = null
postMsgPluginWorker("requestTrans", {text, from, to})
while(true){
await sleep(50)
if(providerRes){
break
}
}
return {
success: translatorRes.success,
content: translatorRes.content
}
} catch (error) {
return {
success: false,
content: "unknownError"
}
}
}
}
export async function pluginProcess(arg:{
prompt_chat: OpenAIChat,
temperature: number,
max_tokens: number,
presence_penalty: number
frequency_penalty: number
bias: {[key:string]:string}
}|{}){
try {
let db = get(DataBase)
if(!pluginWorker){
return {
success: false,
content: "plugin worker not found error"
}
}
postMsgPluginWorker("requestProvider", {
key: db.currentPluginProvider,
arg: arg
})
providerRes = null
while(true){
await sleep(50)
if(providerRes){
break
}
}
return {
success: providerRes.success,
content: providerRes.content
}
} catch (error) {
return {
success: false,
content: "unknownError"
}
}
}