[feat] added translator api to plugin
This commit is contained in:
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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('');
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user