@lobehub/chat 0.67.0 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -0
- package/CHANGELOG.md +25 -0
- package/README-zh_CN.md +4 -1
- package/README.md +4 -1
- package/locales/en_US/plugin.json +8 -2
- package/package.json +2 -2
- package/src/pages/chat/features/Conversation/ChatList/Plugins/IFrameRender/hooks.ts +29 -0
- package/src/pages/chat/features/Conversation/ChatList/Plugins/IFrameRender/index.tsx +62 -0
- package/src/pages/chat/features/Conversation/ChatList/Plugins/IFrameRender/utils.ts +17 -0
- package/src/pages/chat/features/Conversation/ChatList/Plugins/PluginMessage.tsx +20 -4
- package/src/pages/chat/features/Conversation/ChatList/Plugins/{CustomRender.tsx → SystemJsRender/index.tsx} +5 -4
- package/src/store/plugin/selectors.ts +10 -5
- /package/src/pages/chat/features/Conversation/ChatList/Plugins/{dynamticLoader.ts → SystemJsRender/utils.ts} +0 -0
package/.eslintrc.js
CHANGED
|
@@ -11,5 +11,6 @@ config.rules['unicorn/explicit-length-check'] = 0;
|
|
|
11
11
|
config.rules['unicorn/prefer-code-point'] = 0;
|
|
12
12
|
config.rules['no-extra-boolean-cast'] = 0;
|
|
13
13
|
config.rules['unicorn/no-useless-undefined'] = 0;
|
|
14
|
+
config.rules['react/no-unknown-property'] = 0;
|
|
14
15
|
|
|
15
16
|
module.exports = config;
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 0.68.0](https://github.com/lobehub/lobe-chat/compare/v0.67.0...v0.68.0)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2023-09-03**</sup>
|
|
8
|
+
|
|
9
|
+
#### ✨ Features
|
|
10
|
+
|
|
11
|
+
- **misc**: Plugin default use iframe render.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's improved
|
|
19
|
+
|
|
20
|
+
- **misc**: Plugin default use iframe render, closes [#141](https://github.com/lobehub/lobe-chat/issues/141) ([35a3a16](https://github.com/lobehub/lobe-chat/commit/35a3a16))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
## [Version 0.67.0](https://github.com/lobehub/lobe-chat/compare/v0.66.0...v0.67.0)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2023-09-02**</sup>
|
package/README-zh_CN.md
CHANGED
|
@@ -168,7 +168,7 @@ $ pnpm dev
|
|
|
168
168
|
|
|
169
169
|
<!-- CONTRIBUTION GROUP -->
|
|
170
170
|
|
|
171
|
-
> 📊 Total: <kbd>**
|
|
171
|
+
> 📊 Total: <kbd>**5**</kbd>
|
|
172
172
|
|
|
173
173
|
<a href="https://github.com/arvinxx" title="arvinxx">
|
|
174
174
|
<img src="https://avatars.githubusercontent.com/u/28616219?v=4" width="50" />
|
|
@@ -182,6 +182,9 @@ $ pnpm dev
|
|
|
182
182
|
<a href="https://github.com/actions-user" title="actions-user">
|
|
183
183
|
<img src="https://avatars.githubusercontent.com/u/65916846?v=4" width="50" />
|
|
184
184
|
</a>
|
|
185
|
+
<a href="https://github.com/bropines" title="bropines">
|
|
186
|
+
<img src="https://avatars.githubusercontent.com/u/57861007?v=4" width="50" />
|
|
187
|
+
</a>
|
|
185
188
|
|
|
186
189
|
<!-- CONTRIBUTION END -->
|
|
187
190
|
|
package/README.md
CHANGED
|
@@ -168,7 +168,7 @@ Contributions of all types are more than welcome, if you are interested in contr
|
|
|
168
168
|
|
|
169
169
|
<!-- CONTRIBUTION GROUP -->
|
|
170
170
|
|
|
171
|
-
> 📊 Total: <kbd>**
|
|
171
|
+
> 📊 Total: <kbd>**5**</kbd>
|
|
172
172
|
|
|
173
173
|
<a href="https://github.com/arvinxx" title="arvinxx">
|
|
174
174
|
<img src="https://avatars.githubusercontent.com/u/28616219?v=4" width="50" />
|
|
@@ -182,6 +182,9 @@ Contributions of all types are more than welcome, if you are interested in contr
|
|
|
182
182
|
<a href="https://github.com/actions-user" title="actions-user">
|
|
183
183
|
<img src="https://avatars.githubusercontent.com/u/65916846?v=4" width="50" />
|
|
184
184
|
</a>
|
|
185
|
+
<a href="https://github.com/bropines" title="bropines">
|
|
186
|
+
<img src="https://avatars.githubusercontent.com/u/57861007?v=4" width="50" />
|
|
187
|
+
</a>
|
|
185
188
|
|
|
186
189
|
<!-- CONTRIBUTION END -->
|
|
187
190
|
|
|
@@ -52,7 +52,11 @@
|
|
|
52
52
|
"desc": "LobeChat will install the plugin using this link",
|
|
53
53
|
"invalid": "The input manifest link is invalid or does not comply with the specification",
|
|
54
54
|
"label": "Plugin Manifest URL",
|
|
55
|
-
"urlError": "Please enter a valid URL"
|
|
55
|
+
"urlError": "Please enter a valid URL",
|
|
56
|
+
"jsonInvalid": "The manifest is not valid, validation result: \n\n {{error}}",
|
|
57
|
+
"preview": "Preview Manifest",
|
|
58
|
+
"refresh": "Refresh",
|
|
59
|
+
"requestError": "Failed to request the link, please enter a valid link and check if the link allows cross-origin access"
|
|
56
60
|
},
|
|
57
61
|
"title": {
|
|
58
62
|
"desc": "The title of the plugin",
|
|
@@ -73,7 +77,9 @@
|
|
|
73
77
|
"manifest": "Function Description Manifest (Manifest)",
|
|
74
78
|
"meta": "Plugin Metadata"
|
|
75
79
|
},
|
|
76
|
-
"title": "Add Custom Plugin"
|
|
80
|
+
"title": "Add Custom Plugin",
|
|
81
|
+
"update": "Update",
|
|
82
|
+
"updateSuccess": "Plugin settings updated successfully"
|
|
77
83
|
},
|
|
78
84
|
"list": {
|
|
79
85
|
"item": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/chat",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.68.0",
|
|
4
4
|
"description": "Lobe Chat is an open-source chatbot client using LangChain, Typescript and Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatbot",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@emoji-mart/data": "^1",
|
|
67
67
|
"@emoji-mart/react": "^1",
|
|
68
68
|
"@icons-pack/react-simple-icons": "^9",
|
|
69
|
-
"@lobehub/chat-plugin-sdk": "^1.
|
|
69
|
+
"@lobehub/chat-plugin-sdk": "^1.15.0",
|
|
70
70
|
"@lobehub/chat-plugins-gateway": "^1.5.0",
|
|
71
71
|
"@lobehub/ui": "latest",
|
|
72
72
|
"@vercel/analytics": "^1",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
import { onPluginFetchMessage, onPluginReady } from './utils';
|
|
4
|
+
|
|
5
|
+
export const useOnPluginReady = (onReady: () => void) => {
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const fn = (e: MessageEvent) => {
|
|
8
|
+
onPluginReady(e, onReady);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
window.addEventListener('message', fn);
|
|
12
|
+
return () => {
|
|
13
|
+
window.removeEventListener('message', fn);
|
|
14
|
+
};
|
|
15
|
+
}, []);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const useOnPluginFetchMessage = (onRequest: (data: any) => void, deps: any[] = []) => {
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const fn = (e: MessageEvent) => {
|
|
21
|
+
onPluginFetchMessage(e, onRequest);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
window.addEventListener('message', fn);
|
|
25
|
+
return () => {
|
|
26
|
+
window.removeEventListener('message', fn);
|
|
27
|
+
};
|
|
28
|
+
}, deps);
|
|
29
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { PluginRenderProps } from '@lobehub/chat-plugin-sdk';
|
|
2
|
+
import { Skeleton } from 'antd';
|
|
3
|
+
import { memo, useEffect, useRef, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import { useOnPluginFetchMessage, useOnPluginReady } from './hooks';
|
|
6
|
+
import { sendMessageToPlugin } from './utils';
|
|
7
|
+
|
|
8
|
+
interface IFrameRenderProps extends PluginRenderProps {
|
|
9
|
+
height?: number;
|
|
10
|
+
url: string;
|
|
11
|
+
width?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const IFrameRender = memo<IFrameRenderProps>(({ url, width = 800, height = 300, ...props }) => {
|
|
15
|
+
const [loading, setLoading] = useState(true);
|
|
16
|
+
const [readyForRender, setReady] = useState(false);
|
|
17
|
+
const iframeRef = useRef<HTMLIFrameElement>(null);
|
|
18
|
+
|
|
19
|
+
useOnPluginReady(() => setReady(true));
|
|
20
|
+
|
|
21
|
+
// 当 props 发生变化时,主动向 iframe 发送数据
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const iframeWin = iframeRef.current?.contentWindow;
|
|
24
|
+
|
|
25
|
+
if (iframeWin && readyForRender) {
|
|
26
|
+
sendMessageToPlugin(iframeWin, props);
|
|
27
|
+
}
|
|
28
|
+
}, [readyForRender, props]);
|
|
29
|
+
|
|
30
|
+
// 当接收到来自 iframe 的请求时,触发发送数据
|
|
31
|
+
useOnPluginFetchMessage(() => {
|
|
32
|
+
const iframeWin = iframeRef.current?.contentWindow;
|
|
33
|
+
if (iframeWin) {
|
|
34
|
+
sendMessageToPlugin(iframeWin, props);
|
|
35
|
+
}
|
|
36
|
+
}, [props]);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<>
|
|
40
|
+
{loading && <Skeleton active style={{ width }} />}
|
|
41
|
+
<iframe
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
allowtransparency="true"
|
|
44
|
+
height={height}
|
|
45
|
+
hidden={loading}
|
|
46
|
+
onLoad={() => {
|
|
47
|
+
setLoading(false);
|
|
48
|
+
}}
|
|
49
|
+
ref={iframeRef}
|
|
50
|
+
src={url}
|
|
51
|
+
style={{
|
|
52
|
+
border: 0,
|
|
53
|
+
// iframe 在 color-scheme:dark 模式下无法透明
|
|
54
|
+
// refs: https://www.jianshu.com/p/bc5a37bb6a7b
|
|
55
|
+
colorScheme: 'light',
|
|
56
|
+
}}
|
|
57
|
+
width={width}
|
|
58
|
+
/>
|
|
59
|
+
</>
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
export default IFrameRender;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { PluginChannel } from '@lobehub/chat-plugin-sdk';
|
|
2
|
+
|
|
3
|
+
export const onPluginReady = (e: MessageEvent, onReady: () => void) => {
|
|
4
|
+
if (e.data.type === PluginChannel.pluginReadyForRender) {
|
|
5
|
+
onReady();
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const onPluginFetchMessage = (e: MessageEvent, onRequest: (data: any) => void) => {
|
|
10
|
+
if (e.data.type === PluginChannel.fetchPluginMessage) {
|
|
11
|
+
onRequest(e.data);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const sendMessageToPlugin = (window: Window, props: any) => {
|
|
16
|
+
window.postMessage({ props, type: PluginChannel.renderPlugin }, '*');
|
|
17
|
+
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Loading3QuartersOutlined } from '@ant-design/icons';
|
|
2
|
-
import { memo } from 'react';
|
|
2
|
+
import { memo, useMemo } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { Flexbox } from 'react-layout-kit';
|
|
5
5
|
|
|
6
6
|
import { usePluginStore } from '@/store/plugin';
|
|
7
7
|
import { ChatMessage } from '@/types/chatMessage';
|
|
8
8
|
|
|
9
|
-
import
|
|
9
|
+
import IFrameRender from './IFrameRender';
|
|
10
|
+
import SystemJsRender from './SystemJsRender';
|
|
10
11
|
|
|
11
12
|
export interface FunctionMessageProps extends ChatMessage {
|
|
12
13
|
loading?: boolean;
|
|
@@ -23,6 +24,8 @@ const PluginMessage = memo<FunctionMessageProps>(({ content, name }) => {
|
|
|
23
24
|
isJSON = false;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
const contentObj = useMemo(() => (isJSON ? JSON.parse(content) : content), [content]);
|
|
28
|
+
|
|
26
29
|
// if (!loading)
|
|
27
30
|
|
|
28
31
|
if (!isJSON) {
|
|
@@ -36,10 +39,23 @@ const PluginMessage = memo<FunctionMessageProps>(({ content, name }) => {
|
|
|
36
39
|
);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
if (!manifest?.ui
|
|
42
|
+
if (!manifest?.ui) return;
|
|
43
|
+
|
|
44
|
+
const ui = manifest.ui;
|
|
45
|
+
|
|
46
|
+
if (!ui.url) return;
|
|
47
|
+
|
|
48
|
+
if (ui.mode === 'module')
|
|
49
|
+
return <SystemJsRender content={contentObj} name={name || 'unknown'} url={ui.url} />;
|
|
40
50
|
|
|
41
51
|
return (
|
|
42
|
-
<
|
|
52
|
+
<IFrameRender
|
|
53
|
+
content={contentObj}
|
|
54
|
+
height={ui.height}
|
|
55
|
+
name={name || 'unknown'}
|
|
56
|
+
url={ui.url}
|
|
57
|
+
width={ui.width}
|
|
58
|
+
/>
|
|
43
59
|
);
|
|
44
60
|
});
|
|
45
61
|
|
|
@@ -2,12 +2,13 @@ import { PluginRender, PluginRenderProps } from '@lobehub/chat-plugin-sdk';
|
|
|
2
2
|
import { Skeleton } from 'antd';
|
|
3
3
|
import { memo, useEffect, useState } from 'react';
|
|
4
4
|
|
|
5
|
-
import { system } from './
|
|
5
|
+
import { system } from './utils';
|
|
6
6
|
|
|
7
|
-
interface
|
|
7
|
+
interface SystemJsRenderProps extends PluginRenderProps {
|
|
8
8
|
url: string;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
const SystemJsRender = memo<SystemJsRenderProps>(({ url, ...props }) => {
|
|
11
12
|
const [component, setComp] = useState<PluginRender | null>(null);
|
|
12
13
|
|
|
13
14
|
useEffect(() => {
|
|
@@ -31,4 +32,4 @@ const CustomRender = memo<CustomRenderProps>(({ url, ...props }) => {
|
|
|
31
32
|
|
|
32
33
|
return <Render {...props} />;
|
|
33
34
|
});
|
|
34
|
-
export default
|
|
35
|
+
export default SystemJsRender;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { uniqBy } from 'lodash-es';
|
|
2
|
+
import { ChatCompletionFunctions } from 'openai-edge/types/api';
|
|
3
|
+
|
|
1
4
|
import { PLUGIN_SCHEMA_SEPARATOR } from '@/const/plugin';
|
|
2
5
|
import { pluginHelpers } from '@/store/plugin/helpers';
|
|
3
6
|
|
|
@@ -5,12 +8,12 @@ import { PluginStoreState } from './initialState';
|
|
|
5
8
|
|
|
6
9
|
const enabledSchema =
|
|
7
10
|
(enabledPlugins: string[] = []) =>
|
|
8
|
-
(s: PluginStoreState) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// 如果不存在 enabledPlugins,那么全部不启用
|
|
12
|
-
if (!enabledPlugins) return false;
|
|
11
|
+
(s: PluginStoreState): ChatCompletionFunctions[] => {
|
|
12
|
+
// 如果不存在 enabledPlugins,那么全部不启用
|
|
13
|
+
if (!enabledPlugins) return [];
|
|
13
14
|
|
|
15
|
+
const list = Object.values(s.pluginManifestMap)
|
|
16
|
+
.filter((p) => {
|
|
14
17
|
// 如果存在 enabledPlugins,那么只启用 enabledPlugins 中的插件
|
|
15
18
|
return enabledPlugins.includes(p.identifier);
|
|
16
19
|
})
|
|
@@ -21,6 +24,8 @@ const enabledSchema =
|
|
|
21
24
|
name: manifest.identifier + PLUGIN_SCHEMA_SEPARATOR + m.name,
|
|
22
25
|
})),
|
|
23
26
|
);
|
|
27
|
+
|
|
28
|
+
return uniqBy(list, 'name');
|
|
24
29
|
};
|
|
25
30
|
|
|
26
31
|
const pluginList = (s: PluginStoreState) => [...s.pluginList, ...s.customPluginList];
|
|
File without changes
|