Merge pull request #5508 from ConnectAI-E/feature-buildin-plugin
add buildin plugin
This commit is contained in:
commit
649c5be64e
|
@ -12,7 +12,6 @@ import EditIcon from "../icons/edit.svg";
|
||||||
import AddIcon from "../icons/add.svg";
|
import AddIcon from "../icons/add.svg";
|
||||||
import CloseIcon from "../icons/close.svg";
|
import CloseIcon from "../icons/close.svg";
|
||||||
import DeleteIcon from "../icons/delete.svg";
|
import DeleteIcon from "../icons/delete.svg";
|
||||||
import EyeIcon from "../icons/eye.svg";
|
|
||||||
import ConfirmIcon from "../icons/confirm.svg";
|
import ConfirmIcon from "../icons/confirm.svg";
|
||||||
import ReloadIcon from "../icons/reload.svg";
|
import ReloadIcon from "../icons/reload.svg";
|
||||||
import GithubIcon from "../icons/github.svg";
|
import GithubIcon from "../icons/github.svg";
|
||||||
|
@ -29,7 +28,6 @@ import {
|
||||||
import Locale from "../locales";
|
import Locale from "../locales";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { getClientConfig } from "../config/client";
|
|
||||||
|
|
||||||
export function PluginPage() {
|
export function PluginPage() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
@ -209,19 +207,11 @@ export function PluginPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles["mask-actions"]}>
|
<div className={styles["mask-actions"]}>
|
||||||
{m.builtin ? (
|
<IconButton
|
||||||
<IconButton
|
icon={<EditIcon />}
|
||||||
icon={<EyeIcon />}
|
text={Locale.Plugin.Item.Edit}
|
||||||
text={Locale.Plugin.Item.View}
|
onClick={() => setEditingPluginId(m.id)}
|
||||||
onClick={() => setEditingPluginId(m.id)}
|
/>
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<IconButton
|
|
||||||
icon={<EditIcon />}
|
|
||||||
text={Locale.Plugin.Item.Edit}
|
|
||||||
onClick={() => setEditingPluginId(m.id)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!m.builtin && (
|
{!m.builtin && (
|
||||||
<IconButton
|
<IconButton
|
||||||
icon={<DeleteIcon />}
|
icon={<DeleteIcon />}
|
||||||
|
@ -325,23 +315,6 @@ export function PluginPage() {
|
||||||
></PasswordInput>
|
></PasswordInput>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
{!getClientConfig()?.isApp && (
|
|
||||||
<ListItem
|
|
||||||
title={Locale.Plugin.Auth.Proxy}
|
|
||||||
subTitle={Locale.Plugin.Auth.ProxyDescription}
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={editingPlugin?.usingProxy}
|
|
||||||
style={{ minWidth: 16 }}
|
|
||||||
onChange={(e) => {
|
|
||||||
pluginStore.updatePlugin(editingPlugin.id, (plugin) => {
|
|
||||||
plugin.usingProxy = e.currentTarget.checked;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
></input>
|
|
||||||
</ListItem>
|
|
||||||
)}
|
|
||||||
</List>
|
</List>
|
||||||
<List>
|
<List>
|
||||||
<ListItem title={Locale.Plugin.EditModal.Content}>
|
<ListItem title={Locale.Plugin.EditModal.Content}>
|
||||||
|
|
|
@ -2,8 +2,12 @@ import OpenAPIClientAxios from "openapi-client-axios";
|
||||||
import { StoreKey } from "../constant";
|
import { StoreKey } from "../constant";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { createPersistStore } from "../utils/store";
|
import { createPersistStore } from "../utils/store";
|
||||||
|
import { getClientConfig } from "../config/client";
|
||||||
import yaml from "js-yaml";
|
import yaml from "js-yaml";
|
||||||
import { adapter } from "../utils";
|
import { adapter } from "../utils";
|
||||||
|
import { useAccessStore } from "./access";
|
||||||
|
|
||||||
|
const isApp = getClientConfig()?.isApp;
|
||||||
|
|
||||||
export type Plugin = {
|
export type Plugin = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -16,7 +20,6 @@ export type Plugin = {
|
||||||
authLocation?: string;
|
authLocation?: string;
|
||||||
authHeader?: string;
|
authHeader?: string;
|
||||||
authToken?: string;
|
authToken?: string;
|
||||||
usingProxy?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FunctionToolItem = {
|
export type FunctionToolItem = {
|
||||||
|
@ -46,18 +49,25 @@ export const FunctionToolService = {
|
||||||
plugin?.authType == "basic"
|
plugin?.authType == "basic"
|
||||||
? `Basic ${plugin?.authToken}`
|
? `Basic ${plugin?.authToken}`
|
||||||
: plugin?.authType == "bearer"
|
: plugin?.authType == "bearer"
|
||||||
? ` Bearer ${plugin?.authToken}`
|
? `Bearer ${plugin?.authToken}`
|
||||||
: plugin?.authToken;
|
: plugin?.authToken;
|
||||||
const authLocation = plugin?.authLocation || "header";
|
const authLocation = plugin?.authLocation || "header";
|
||||||
const definition = yaml.load(plugin.content) as any;
|
const definition = yaml.load(plugin.content) as any;
|
||||||
const serverURL = definition?.servers?.[0]?.url;
|
const serverURL = definition?.servers?.[0]?.url;
|
||||||
const baseURL = !!plugin?.usingProxy ? "/api/proxy" : serverURL;
|
const baseURL = !isApp ? "/api/proxy" : serverURL;
|
||||||
const headers: Record<string, string | undefined> = {
|
const headers: Record<string, string | undefined> = {
|
||||||
"X-Base-URL": !!plugin?.usingProxy ? serverURL : undefined,
|
"X-Base-URL": !isApp ? serverURL : undefined,
|
||||||
};
|
};
|
||||||
if (authLocation == "header") {
|
if (authLocation == "header") {
|
||||||
headers[headerName] = tokenValue;
|
headers[headerName] = tokenValue;
|
||||||
}
|
}
|
||||||
|
// try using openaiApiKey for Dalle3 Plugin.
|
||||||
|
if (!tokenValue && plugin.id === "dalle3") {
|
||||||
|
const openaiApiKey = useAccessStore.getState().openaiApiKey;
|
||||||
|
if (openaiApiKey) {
|
||||||
|
headers[headerName] = `Bearer ${openaiApiKey}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
const api = new OpenAPIClientAxios({
|
const api = new OpenAPIClientAxios({
|
||||||
definition: yaml.load(plugin.content) as any,
|
definition: yaml.load(plugin.content) as any,
|
||||||
axiosConfigDefaults: {
|
axiosConfigDefaults: {
|
||||||
|
@ -165,7 +175,7 @@ export const usePluginStore = createPersistStore(
|
||||||
(set, get) => ({
|
(set, get) => ({
|
||||||
create(plugin?: Partial<Plugin>) {
|
create(plugin?: Partial<Plugin>) {
|
||||||
const plugins = get().plugins;
|
const plugins = get().plugins;
|
||||||
const id = nanoid();
|
const id = plugin?.id || nanoid();
|
||||||
plugins[id] = {
|
plugins[id] = {
|
||||||
...createEmptyPlugin(),
|
...createEmptyPlugin(),
|
||||||
...plugin,
|
...plugin,
|
||||||
|
@ -220,5 +230,42 @@ export const usePluginStore = createPersistStore(
|
||||||
{
|
{
|
||||||
name: StoreKey.Plugin,
|
name: StoreKey.Plugin,
|
||||||
version: 1,
|
version: 1,
|
||||||
|
onRehydrateStorage(state) {
|
||||||
|
// Skip store rehydration on server side
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch("./plugins.json")
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((res) => {
|
||||||
|
Promise.all(
|
||||||
|
res.map((item: any) =>
|
||||||
|
// skip get schema
|
||||||
|
state.get(item.id)
|
||||||
|
? item
|
||||||
|
: fetch(item.schema)
|
||||||
|
.then((res) => res.text())
|
||||||
|
.then((content) => ({
|
||||||
|
...item,
|
||||||
|
content,
|
||||||
|
}))
|
||||||
|
.catch((e) => item),
|
||||||
|
),
|
||||||
|
).then((builtinPlugins: any) => {
|
||||||
|
builtinPlugins
|
||||||
|
.filter((item: any) => item?.content)
|
||||||
|
.forEach((item: any) => {
|
||||||
|
const plugin = state.create(item);
|
||||||
|
state.updatePlugin(plugin.id, (plugin) => {
|
||||||
|
const tool = FunctionToolService.add(plugin, true);
|
||||||
|
plugin.title = tool.api.definition.info.title;
|
||||||
|
plugin.version = tool.api.definition.info.version;
|
||||||
|
plugin.builtin = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "dalle3",
|
||||||
|
"name": "Dalle3",
|
||||||
|
"schema": "https://ghp.ci/https://raw.githubusercontent.com/ChatGPTNextWeb/NextChat-Awesome-Plugins/main/plugins/dalle/openapi.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "arxivsearch",
|
||||||
|
"name": "ArxivSearch",
|
||||||
|
"schema": "https://ghp.ci/https://raw.githubusercontent.com/ChatGPTNextWeb/NextChat-Awesome-Plugins/main/plugins/arxivsearch/openapi.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "duckduckgolite",
|
||||||
|
"name": "DuckDuckGoLiteSearch",
|
||||||
|
"schema": "https://ghp.ci/https://raw.githubusercontent.com/ChatGPTNextWeb/NextChat-Awesome-Plugins/main/plugins/duckduckgolite/openapi.json"
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in New Issue