stash code

This commit is contained in:
lloydzhou 2024-08-29 19:55:09 +08:00
parent d2cb984ced
commit 571ce11e53
5 changed files with 213 additions and 5 deletions

View File

@ -14,6 +14,7 @@ import {
useAccessStore,
useAppConfig,
useChatStore,
usePluginStore,
} from "@/app/store";
import { collectModelsWithDefaultModel } from "@/app/utils/model";
import {
@ -240,6 +241,11 @@ export class ChatGPTApi implements LLMApi {
);
}
if (shouldStream) {
const [tools1, funcs2] = usePluginStore
.getState()
.getAsTools(useChatStore.getState().currentSession().mask?.plugin);
console.log("getAsTools", tools1, funcs2);
// return
// TODO mock tools and funcs
const tools = [
{
@ -276,8 +282,8 @@ export class ChatGPTApi implements LLMApi {
chatPath,
requestPayload,
getHeaders(),
tools,
funcs,
tools1,
funcs2,
controller,
// parseSSE
(text: string, runTools: ChatMessageTool[]) => {

View File

@ -54,6 +54,7 @@ import {
useAppConfig,
DEFAULT_TOPIC,
ModelType,
usePluginStore,
} from "../store";
import {
@ -440,6 +441,71 @@ export function ChatActions(props: {
const config = useAppConfig();
const navigate = useNavigate();
const chatStore = useChatStore();
const pluginStore = usePluginStore();
console.log("pluginStore", pluginStore.getAll());
// test
if (pluginStore.getAll().length == 0) {
pluginStore.create({
title: "Pet API",
version: "1.0.0",
content: `{
"openapi": "3.0.2",
"info": {
"title": "Pet API",
"version": "1.0.0"
},
"paths": {
"/api/pets": {
"get": {
"operationId": "getPets",
"description": "Returns all pets from the system that the user has access to",
"responses": {
"200": {
"description": "List of Pets",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"cat",
"dog"
]
},
"name": {
"type": "string"
}
},
"required": [
"id",
"type"
]
}
}
}
}`,
});
}
// switch themes
const theme = config.theme;
@ -738,15 +804,22 @@ export function ChatActions(props: {
title: Locale.Plugin.Artifacts,
value: Plugin.Artifacts,
},
]}
].concat(
pluginStore
.getAll()
.map((item) => ({
title: `${item.title}@${item.version}`,
value: item.id,
})),
)}
onClose={() => setShowPluginSelector(false)}
onSelection={(s) => {
const plugin = s[0];
chatStore.updateCurrentSession((session) => {
session.mask.plugin = s;
});
if (plugin) {
showToast(plugin);
if (s.includes(Plugin.Artifacts)) {
showToast(Plugin.Artifacts);
}
}}
/>

View File

@ -78,6 +78,7 @@ export enum Plugin {
export enum StoreKey {
Chat = "chat-next-web-store",
Plugin = "chat-next-web-plugin",
Access = "access-control",
Config = "app-config",
Mask = "mask-store",

View File

@ -2,3 +2,4 @@ export * from "./chat";
export * from "./update";
export * from "./access";
export * from "./config";
export * from "./plugin";

127
app/store/plugin.ts Normal file
View File

@ -0,0 +1,127 @@
import OpenAPIClientAxios from "openapi-client-axios";
import { getLang, Lang } from "../locales";
import { StoreKey, Plugin } from "../constant";
import { nanoid } from "nanoid";
import { createPersistStore } from "../utils/store";
import yaml from "js-yaml";
export type Plugin = {
id: string;
createdAt: number;
title: string;
version: string;
context: string;
builtin: boolean;
};
export const createEmptyPlugin = () =>
({
id: nanoid(),
title: "",
version: "",
context: "",
builtin: false,
createdAt: Date.now(),
}) as Plugin;
export const DEFAULT_PLUGIN_STATE = {
plugins: {} as Record<string, Plugin>,
};
export const usePluginStore = createPersistStore(
{ ...DEFAULT_PLUGIN_STATE },
(set, get) => ({
create(plugin?: Partial<Plugin>) {
const plugins = get().plugins;
const id = nanoid();
plugins[id] = {
...createEmptyPlugin(),
...plugin,
id,
builtin: false,
};
set(() => ({ plugins }));
get().markUpdate();
return plugins[id];
},
updatePlugin(id: string, updater: (plugin: Plugin) => void) {
const plugins = get().plugins;
const plugin = plugins[id];
if (!plugin) return;
const updatePlugin = { ...plugin };
updater(updatePlugin);
plugins[id] = updatePlugin;
set(() => ({ plugins }));
get().markUpdate();
},
delete(id: string) {
const plugins = get().plugins;
delete plugins[id];
set(() => ({ plugins }));
get().markUpdate();
},
getAsTools(ids: string[]) {
const plugins = get().plugins;
const selected = ids
.map((id) => plugins[id])
.filter((i) => i)
.map((i) => [
i,
new OpenAPIClientAxios({ definition: yaml.load(i.content) }),
])
.map(([item, api]) => {
api.initSync();
const operations = api.getOperations().map((o) => {
const parameters = o.parameters;
return [
{
type: "function",
function: {
name: o.operationId,
description: o.description,
parameters: o.parameters,
},
},
api.client[o.operationId],
];
// return [{
// }, function(arg) {
// const args = []
// for (const p in parameters) {
// if (p.type === "object") {
// const a = {}
// for (const n of p.)
// }
// }
// }]
});
return [item, api, operations];
});
console.log("selected", selected);
const result = selected.reduce((s, i) => s.concat(i[2]), []);
return [
result.map(([t, _]) => t),
result.reduce((s, i) => {
s[i[0].function.name] = i[1];
return s;
}, {}),
];
},
get(id?: string) {
return get().plugins[id ?? 1145141919810];
},
getAll() {
return Object.values(get().plugins).sort(
(a, b) => b.createdAt - a.createdAt,
);
},
}),
{
name: StoreKey.Plugin,
version: 1,
},
);