[feat] added translator api to plugin

This commit is contained in:
kwaroran
2023-05-07 22:03:43 +09:00
parent acbf4b0cc2
commit 10863cee51
3 changed files with 202 additions and 132 deletions

View File

@@ -1,143 +1,147 @@
interface risuPlugin{ (() => {
providers: {name:string, func:(arg:providerArgument) => Promise<{success:boolean,content:string}>}[] interface risuPlugin{
fetchResponseQueue:{id:string,data:any}[] providers: {name:string, func:(arg:providerArgument) => Promise<{success:boolean,content:string}>}[]
} fetchResponseQueue:{id:string,data:any}[]
let __risuPlugin__:risuPlugin = {
providers: [],
fetchResponseQueue: []
}
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
interface OpenAIChat{
role: 'system'|'user'|'assistant'
content: string
}
interface providerArgument{
prompt_chat?: OpenAIChat,
temperature?: number,
max_tokens?: number,
presence_penalty?: number
frequency_penalty?: number
bias?: {[key:string]:string}
}
async function risuFetch(url:string, arg:{body:any,headers?:{[key:string]:string}}){
const id = `${Date.now()}_${Math.random()}`
postMessage({
type: 'fetch',
body: {
id: id,
url: url,
arg: arg
}
})
while(true){
await sleep(50)
for(let i=0;i<__risuPlugin__.fetchResponseQueue.length;i++){
const q = __risuPlugin__.fetchResponseQueue[i]
if(q.id === id){
__risuPlugin__.fetchResponseQueue.splice(i, 1)
return q.data as {
ok: boolean;
data: any;
}
}
}
} }
}
let __risuPlugin__:risuPlugin = {
async function getArg(arg:string){ providers: [],
const id = `${Date.now()}_${Math.random()}` fetchResponseQueue: []
postMessage({
type: 'getArg',
body: {
id: id,
arg: arg
}
})
while(true){
await sleep(50)
for(let i=0;i<__risuPlugin__.fetchResponseQueue.length;i++){
const q = __risuPlugin__.fetchResponseQueue[i]
if(q.id === id){
__risuPlugin__.fetchResponseQueue.splice(i, 1)
return q.data as (string|number|null)
}
}
} }
}
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
function addProvider(name:string, func:(arg:providerArgument) => Promise<{success:boolean,content:string}>){
postMessage({ interface OpenAIChat{
type: 'addProvider', role: 'system'|'user'|'assistant'
body: name content: string
})
__risuPlugin__.providers.push({
name: name,
func: func
})
}
function printLog(data:any){
postMessage({
type: 'log',
body: data
})
}
async function handleOnmessage(data:{type:string,body:any}) {
if(!data.type){
return
} }
switch(data.type){
case "requestProvider":{ interface providerArgument{
const body:{key:string,arg:providerArgument} = data.body prompt_chat?: OpenAIChat,
const providers = __risuPlugin__.providers temperature?: number,
let providerfunc:((arg:providerArgument) => Promise<{success:boolean,content:string}>)|null= null max_tokens?: number,
for(const provider of providers){ presence_penalty?: number
if(provider.name === body.key){ frequency_penalty?: number
providerfunc = provider.func bias?: {[key:string]:string}
} }
async function risuFetch(url:string, arg:{body:any,headers?:{[key:string]:string}}){
const id = `${Date.now()}_${Math.random()}`
postMessage({
type: 'fetch',
body: {
id: id,
url: url,
arg: arg
} }
if(!providerfunc){ })
postMessage({ while(true){
type: 'resProvider', await sleep(50)
body: { for(let i=0;i<__risuPlugin__.fetchResponseQueue.length;i++){
'success': false, const q = __risuPlugin__.fetchResponseQueue[i]
'content': 'unknown provider' if(q.id === id){
__risuPlugin__.fetchResponseQueue.splice(i, 1)
return q.data as {
ok: boolean;
data: any;
} }
}) }
} }
else{ }
try { }
postMessage({
type: 'resProvider', async function getArg(arg:string){
body: await providerfunc(body.arg) const id = `${Date.now()}_${Math.random()}`
}) postMessage({
} catch (error) { type: 'getArg',
body: {
id: id,
arg: arg
}
})
while(true){
await sleep(50)
for(let i=0;i<__risuPlugin__.fetchResponseQueue.length;i++){
const q = __risuPlugin__.fetchResponseQueue[i]
if(q.id === id){
__risuPlugin__.fetchResponseQueue.splice(i, 1)
return q.data as (string|number|null)
}
}
}
}
function addProvider(name:string, func:(arg:providerArgument) => Promise<{success:boolean,content:string}>){
postMessage({
type: 'addProvider',
body: name
})
__risuPlugin__.providers.push({
name: name,
func: func
})
}
function printLog(data:any){
postMessage({
type: 'log',
body: data
})
}
async function handleOnmessage(data:{type:string,body:any}) {
if(!data.type){
return
}
switch(data.type){
case "requestProvider":{
const body:{key:string,arg:providerArgument} = data.body
const providers = __risuPlugin__.providers
let providerfunc:((arg:providerArgument) => Promise<{success:boolean,content:string}>)|null= null
for(const provider of providers){
if(provider.name === body.key){
providerfunc = provider.func
}
}
if(!providerfunc){
postMessage({ postMessage({
type: 'resProvider', type: 'resProvider',
body: { body: {
'success': false, 'success': false,
'content': `providerError: ${error}` 'content': 'unknown provider'
} }
}) })
} }
else{
try {
postMessage({
type: 'resProvider',
body: await providerfunc(body.arg)
})
} catch (error) {
postMessage({
type: 'resProvider',
body: {
'success': false,
'content': `providerError: ${error}`
}
})
}
}
break
}
case "fetchData":{
__risuPlugin__.fetchResponseQueue.push(data.body)
break
} }
break
}
case "fetchData":{
__risuPlugin__.fetchResponseQueue.push(data.body)
break
} }
} }
}
onmessage = (ev) => {
handleOnmessage(ev.data)
const data:{type:string,body:any} = ev.data
}
onmessage = (ev) => { //{{placeholder}}
handleOnmessage(ev.data) })()
const data:{type:string,body:any} = ev.data
}

View File

@@ -107,6 +107,7 @@ export function getCurrentPluginMax(prov:string){
let pluginWorker:Worker = null let pluginWorker:Worker = null
let providerRes:{success:boolean, content:string} = null let providerRes:{success:boolean, content:string} = null
let translatorRes:{success:boolean, content:string} = null
function postMsgPluginWorker(type:string, body:any){ function postMsgPluginWorker(type:string, body:any){
const bod = { const bod = {
@@ -116,6 +117,8 @@ function postMsgPluginWorker(type:string, body:any){
pluginWorker.postMessage(bod) pluginWorker.postMessage(bod)
} }
let pluginTranslator = false
export async function loadPlugins() { export async function loadPlugins() {
let db = get(DataBase) let db = get(DataBase)
if(pluginWorker){ if(pluginWorker){
@@ -127,10 +130,12 @@ export async function loadPlugins() {
const da = await fetch("/pluginApi.js") const da = await fetch("/pluginApi.js")
const pluginApiString = await da.text() const pluginApiString = await da.text()
let pluginjs = `${pluginApiString}\n` let pluginjs = `${pluginApiString}\n`
let pluginLoadedJs = ''
for(const plug of db.plugins){ for(const plug of db.plugins){
pluginjs += `(() => {${plug.script}})()` pluginLoadedJs += `(() => {${plug.script}})()`
} }
pluginjs = pluginjs.replace('//{{placeholder}}',pluginLoadedJs)
const blob = new Blob([pluginjs], {type: 'application/javascript'}); const blob = new Blob([pluginjs], {type: 'application/javascript'});
pluginWorker = new Worker(URL.createObjectURL(blob)); pluginWorker = new Worker(URL.createObjectURL(blob));
@@ -167,6 +172,31 @@ export async function loadPlugins() {
} }
break 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": { case "fetch": {
postMsgPluginWorker('fetchData',{ postMsgPluginWorker('fetchData',{
id: data.body.id, id: data.body.id,
@@ -208,6 +238,33 @@ export async function loadPlugins() {
} }
} }
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:{ export async function pluginProcess(arg:{
prompt_chat: OpenAIChat, prompt_chat: OpenAIChat,
temperature: number, temperature: number,

View File

@@ -1,28 +1,34 @@
import { Body,fetch,ResponseType } from "@tauri-apps/api/http" import { Body,fetch,ResponseType } from "@tauri-apps/api/http"
import { isTauri } from "../globalApi" import { isTauri } from "../globalApi"
import { translatorPlugin } from "../process/plugins"
let cache={ let cache={
origin: [''], origin: [''],
trans: [''] trans: ['']
} }
export async function translate(params:string, reverse:boolean) { export async function translate(text:string, reverse:boolean) {
if(!isTauri){ if(!isTauri){
return params return text
}
const plug = await translatorPlugin(text, reverse ? 'ko' : 'en', reverse ? 'en' : 'ko')
if(plug){
return plug.content
} }
if(!reverse){ if(!reverse){
const ind = cache.origin.indexOf(params) const ind = cache.origin.indexOf(text)
if(ind !== -1){ if(ind !== -1){
return cache.trans[ind] return cache.trans[ind]
} }
} }
else{ else{
const ind = cache.trans.indexOf(params) const ind = cache.trans.indexOf(text)
if(ind !== -1){ if(ind !== -1){
return cache.origin[ind] return cache.origin[ind]
} }
} }
return googleTrans(params, reverse)
return googleTrans(text, reverse)
} }
async function googleTrans(text:string, reverse:boolean) { async function googleTrans(text:string, reverse:boolean) {
@@ -45,5 +51,8 @@ async function googleTrans(text:string, reverse:boolean) {
}) })
const res = f.data as {sentences:{trans?:string}[]} const res = f.data as {sentences:{trans?:string}[]}
if(typeof(f.data) === 'string'){
return res
}
return res.sentences.filter((s) => 'trans' in s).map((s) => s.trans).join(''); return res.sentences.filter((s) => 'trans' in s).map((s) => s.trans).join('');
} }