@lobehub/chat 0.54.4 → 0.55.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 +56 -0
- package/package.json +6 -3
- package/src/components/SelectWithImg/styles.ts +8 -7
- package/src/const/url.ts +4 -0
- package/src/features/AgentSetting/AgentPlugin/index.tsx +83 -20
- package/src/layout/index.tsx +13 -8
- package/src/locales/default/plugin.ts +0 -16
- package/src/pages/api/openai.ts +4 -20
- package/src/pages/api/plugins.api.ts +161 -8
- package/src/pages/chat/[id]/layout.tsx +4 -0
- package/src/pages/chat/features/Conversation/ChatList/Plugins/CustomRender.tsx +32 -0
- package/src/pages/chat/features/Conversation/ChatList/Plugins/FunctionCall.tsx +4 -5
- package/src/pages/chat/features/Conversation/ChatList/Plugins/PluginMessage.tsx +36 -27
- package/src/pages/chat/features/Conversation/ChatList/Plugins/dynamticLoader.ts +26 -0
- package/src/pages/chat/features/Header/PluginTag.tsx +13 -8
- package/src/services/chatModel.ts +11 -2
- package/src/services/plugin.ts +11 -1
- package/src/store/plugin/action.ts +121 -0
- package/src/store/plugin/hooks/useSessionHydrated.ts +21 -0
- package/src/store/plugin/index.ts +2 -0
- package/src/store/plugin/initialState.ts +19 -0
- package/src/store/plugin/reducers/manifest.ts +36 -0
- package/src/store/plugin/selectors.ts +23 -0
- package/src/store/plugin/store.ts +48 -0
- package/src/store/session/hooks/useOnFinishHydrationSession.ts +6 -3
- package/src/store/session/hooks/useSessionHydrated.ts +0 -1
- package/src/store/session/slices/agentConfig/action.ts +2 -6
- package/src/store/session/slices/chat/selectors/utils.test.ts +15 -1
- package/src/store/session/slices/chat/selectors/utils.ts +5 -3
- package/src/store/session/store.ts +0 -1
- package/src/types/plugin.ts +3 -4
- package/src/plugins/Render.ts +0 -11
- package/src/plugins/index.ts +0 -11
- package/src/plugins/searchEngine/Render.tsx +0 -92
- package/src/plugins/searchEngine/index.ts +0 -26
- package/src/plugins/searchEngine/type.ts +0 -82
- package/src/plugins/type.ts +0 -45
- package/src/plugins/weather/Render.tsx +0 -53
- package/src/plugins/weather/index.ts +0 -24
- package/src/plugins/weather/type.ts +0 -36
- package/src/plugins/webCrawler/index.ts +0 -20
- package/src/plugins/webCrawler/type.ts +0 -35
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { createStyles } from 'antd-style';
|
|
2
|
-
import Image from 'next/image';
|
|
3
|
-
import Link from 'next/link';
|
|
4
|
-
import { memo } from 'react';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
|
|
7
|
-
import { PluginRenderProps } from '@/plugins/type';
|
|
8
|
-
|
|
9
|
-
import { Result } from './type';
|
|
10
|
-
|
|
11
|
-
const useStyles = createStyles(({ css, token, cx }) => {
|
|
12
|
-
const title = css`
|
|
13
|
-
margin-top: 4px;
|
|
14
|
-
font-size: 16px;
|
|
15
|
-
`;
|
|
16
|
-
return {
|
|
17
|
-
container: css`
|
|
18
|
-
overflow: scroll;
|
|
19
|
-
max-height: 370px;
|
|
20
|
-
`,
|
|
21
|
-
desc: css`
|
|
22
|
-
color: ${token.colorTextTertiary};
|
|
23
|
-
`,
|
|
24
|
-
displayLink: css`
|
|
25
|
-
color: ${token.colorTextQuaternary};
|
|
26
|
-
`,
|
|
27
|
-
favicon: css`
|
|
28
|
-
border-radius: 50%;
|
|
29
|
-
`,
|
|
30
|
-
item: css`
|
|
31
|
-
:not(:last-child) {
|
|
32
|
-
border-bottom: 1px solid ${token.colorBorder};
|
|
33
|
-
}
|
|
34
|
-
`,
|
|
35
|
-
link: css`
|
|
36
|
-
&:hover {
|
|
37
|
-
.${cx(title)} {
|
|
38
|
-
text-decoration: underline;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
`,
|
|
42
|
-
title,
|
|
43
|
-
};
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const Render = memo<PluginRenderProps<Result>>(({ content }) => {
|
|
47
|
-
const { styles } = useStyles();
|
|
48
|
-
return (
|
|
49
|
-
<Flexbox className={styles.container}>
|
|
50
|
-
{content.map((item, index) => (
|
|
51
|
-
<Flexbox
|
|
52
|
-
className={styles.item}
|
|
53
|
-
distribution={'space-between'}
|
|
54
|
-
horizontal
|
|
55
|
-
key={item.link}
|
|
56
|
-
padding={12}
|
|
57
|
-
>
|
|
58
|
-
<Flexbox>
|
|
59
|
-
<Link className={styles.link} href={item.link!} target={'_blank'}>
|
|
60
|
-
<Flexbox>
|
|
61
|
-
<Flexbox align={'center'} gap={12} horizontal>
|
|
62
|
-
{item.favicon && (
|
|
63
|
-
<Image
|
|
64
|
-
alt={item.title || item.link}
|
|
65
|
-
className={styles.favicon}
|
|
66
|
-
height={24}
|
|
67
|
-
src={item.favicon}
|
|
68
|
-
unoptimized
|
|
69
|
-
width={24}
|
|
70
|
-
/>
|
|
71
|
-
)}
|
|
72
|
-
<Flexbox>
|
|
73
|
-
<Flexbox className={styles.desc}>{item.source}</Flexbox>
|
|
74
|
-
<Flexbox className={styles.displayLink}>{item.displayed_link}</Flexbox>
|
|
75
|
-
</Flexbox>
|
|
76
|
-
</Flexbox>
|
|
77
|
-
<Flexbox align={'baseline'} gap={2} horizontal>
|
|
78
|
-
<div>{index + 1}.</div>
|
|
79
|
-
<Flexbox className={styles.title}>{item.title}</Flexbox>
|
|
80
|
-
</Flexbox>
|
|
81
|
-
</Flexbox>
|
|
82
|
-
</Link>
|
|
83
|
-
<Flexbox className={styles.desc}>
|
|
84
|
-
{item.date ? `${item.date} - ${item.content}` : item.content}
|
|
85
|
-
</Flexbox>
|
|
86
|
-
</Flexbox>
|
|
87
|
-
</Flexbox>
|
|
88
|
-
))}
|
|
89
|
-
</Flexbox>
|
|
90
|
-
);
|
|
91
|
-
});
|
|
92
|
-
export default Render;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ChatCompletionFunctions } from 'openai-edge/types/api';
|
|
2
|
-
|
|
3
|
-
import { PluginItem } from '@/plugins/type';
|
|
4
|
-
|
|
5
|
-
const schema: ChatCompletionFunctions = {
|
|
6
|
-
description: '查询搜索引擎获取信息',
|
|
7
|
-
name: 'searchEngine',
|
|
8
|
-
parameters: {
|
|
9
|
-
properties: {
|
|
10
|
-
keywords: {
|
|
11
|
-
description: '关键词',
|
|
12
|
-
type: 'string',
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
required: ['keywords'],
|
|
16
|
-
type: 'object',
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const searchEngine: PluginItem = {
|
|
21
|
-
avatar: '🔍',
|
|
22
|
-
name: 'searchEngine',
|
|
23
|
-
schema,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default searchEngine;
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
export type OrganicResults = OrganicResult[];
|
|
2
|
-
|
|
3
|
-
export interface SearchItem {
|
|
4
|
-
content: string;
|
|
5
|
-
date?: string;
|
|
6
|
-
displayed_link?: string;
|
|
7
|
-
favicon?: string;
|
|
8
|
-
link: string;
|
|
9
|
-
source?: string;
|
|
10
|
-
title: string;
|
|
11
|
-
}
|
|
12
|
-
export type Result = SearchItem[];
|
|
13
|
-
|
|
14
|
-
interface OrganicResult {
|
|
15
|
-
about_page_link: string;
|
|
16
|
-
about_page_serpapi_link: string;
|
|
17
|
-
about_this_result: AboutThisResult;
|
|
18
|
-
cached_page_link?: string;
|
|
19
|
-
date?: string;
|
|
20
|
-
displayed_link: string;
|
|
21
|
-
favicon?: string;
|
|
22
|
-
link: string;
|
|
23
|
-
position: number;
|
|
24
|
-
related_results?: RelatedResult[];
|
|
25
|
-
rich_snippet?: RichSnippet;
|
|
26
|
-
snippet: string;
|
|
27
|
-
snippet_highlighted_words?: string[];
|
|
28
|
-
source: string;
|
|
29
|
-
thumbnail?: string;
|
|
30
|
-
title: string;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
interface AboutThisResult {
|
|
34
|
-
languages: string[];
|
|
35
|
-
regions: string[];
|
|
36
|
-
source: Source;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
interface Source {
|
|
40
|
-
description: string;
|
|
41
|
-
icon: string;
|
|
42
|
-
security?: string;
|
|
43
|
-
source_info_link?: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
interface RelatedResult {
|
|
47
|
-
about_page_link: string;
|
|
48
|
-
about_page_serpapi_link: string;
|
|
49
|
-
about_this_result: AboutThisResult2;
|
|
50
|
-
cached_page_link: string;
|
|
51
|
-
date: string;
|
|
52
|
-
displayed_link: string;
|
|
53
|
-
link: string;
|
|
54
|
-
position: number;
|
|
55
|
-
snippet: string;
|
|
56
|
-
snippet_highlighted_words: string[];
|
|
57
|
-
title: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
interface AboutThisResult2 {
|
|
61
|
-
languages: string[];
|
|
62
|
-
regions: string[];
|
|
63
|
-
source: Source2;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface Source2 {
|
|
67
|
-
description: string;
|
|
68
|
-
icon: string;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
interface RichSnippet {
|
|
72
|
-
top: Top;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
interface Top {
|
|
76
|
-
detected_extensions: DetectedExtensions;
|
|
77
|
-
extensions: string[];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
interface DetectedExtensions {
|
|
81
|
-
month_ago: number;
|
|
82
|
-
}
|
package/src/plugins/type.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { ChatCompletionFunctions } from 'openai-edge/types/api';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* 插件项
|
|
6
|
-
* @template Result - 结果类型,默认为 any
|
|
7
|
-
* @template RunnerParams - 运行参数类型,默认为 any
|
|
8
|
-
*/
|
|
9
|
-
export interface PluginItem {
|
|
10
|
-
/**
|
|
11
|
-
* 头像
|
|
12
|
-
*/
|
|
13
|
-
avatar: string;
|
|
14
|
-
/**
|
|
15
|
-
* 名称
|
|
16
|
-
*/
|
|
17
|
-
name: string;
|
|
18
|
-
render?: PluginRender;
|
|
19
|
-
/**
|
|
20
|
-
* 聊天完成函数的模式
|
|
21
|
-
*/
|
|
22
|
-
schema: ChatCompletionFunctions;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* 插件渲染函数
|
|
27
|
-
* @param props - 插件渲染属性
|
|
28
|
-
* @returns React 节点
|
|
29
|
-
*/
|
|
30
|
-
export type PluginRender = (props: PluginRenderProps) => ReactNode;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* 插件渲染属性
|
|
34
|
-
* @template Result - 结果类型,默认为 any
|
|
35
|
-
*/
|
|
36
|
-
export interface PluginRenderProps<Result = any> {
|
|
37
|
-
/**
|
|
38
|
-
* 内容
|
|
39
|
-
*/
|
|
40
|
-
content: Result;
|
|
41
|
-
/**
|
|
42
|
-
* 名称
|
|
43
|
-
*/
|
|
44
|
-
name: string;
|
|
45
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { Table } from 'antd';
|
|
2
|
-
import { createStyles } from 'antd-style';
|
|
3
|
-
import { memo } from 'react';
|
|
4
|
-
import { useTranslation } from 'react-i18next';
|
|
5
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
-
|
|
7
|
-
import { PluginRenderProps } from '@/plugins/type';
|
|
8
|
-
|
|
9
|
-
import { WeatherResult } from './type';
|
|
10
|
-
|
|
11
|
-
const useStyles = createStyles(({ css, token }) => ({
|
|
12
|
-
time: css`
|
|
13
|
-
color: ${token.colorTextQuaternary};
|
|
14
|
-
`,
|
|
15
|
-
title: css`
|
|
16
|
-
font-weight: bold;
|
|
17
|
-
`,
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
const Render = memo<PluginRenderProps<WeatherResult>>(({ content }) => {
|
|
21
|
-
const { t } = useTranslation('plugin');
|
|
22
|
-
|
|
23
|
-
const { styles } = useStyles();
|
|
24
|
-
return (
|
|
25
|
-
<div>
|
|
26
|
-
{content.map((item, index) => (
|
|
27
|
-
<Flexbox gap={8} key={`${item.city}-${index}`}>
|
|
28
|
-
<Flexbox align={'center'} distribution={'space-between'} horizontal>
|
|
29
|
-
<div className={styles.title}>{t('realtimeWeather.title', { city: item.city })}</div>
|
|
30
|
-
<div className={styles.time}>
|
|
31
|
-
{t('realtimeWeather.updateAt')}: {item.reporttime}
|
|
32
|
-
</div>
|
|
33
|
-
</Flexbox>
|
|
34
|
-
<Table
|
|
35
|
-
bordered
|
|
36
|
-
columns={[
|
|
37
|
-
{ dataIndex: 'date', title: t('realtimeWeather.data.date') },
|
|
38
|
-
{ dataIndex: 'week', title: t('realtimeWeather.data.week') },
|
|
39
|
-
{ dataIndex: 'dayweather', title: t('realtimeWeather.data.dayweather') },
|
|
40
|
-
{ dataIndex: 'daytemp_float', title: t('realtimeWeather.data.daytemp_float') },
|
|
41
|
-
{ dataIndex: 'daywind', title: t('realtimeWeather.data.daywind') },
|
|
42
|
-
{ dataIndex: 'nightweather', title: t('realtimeWeather.data.nightweather') },
|
|
43
|
-
{ dataIndex: 'nighttemp_float', title: t('realtimeWeather.data.nighttemp_float') },
|
|
44
|
-
]}
|
|
45
|
-
dataSource={item.casts}
|
|
46
|
-
pagination={false}
|
|
47
|
-
/>
|
|
48
|
-
</Flexbox>
|
|
49
|
-
))}
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
});
|
|
53
|
-
export default Render;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { PluginItem } from '@/plugins/type';
|
|
2
|
-
|
|
3
|
-
const schema = {
|
|
4
|
-
description: '获取当前天气情况',
|
|
5
|
-
name: 'realtimeWeather',
|
|
6
|
-
parameters: {
|
|
7
|
-
properties: {
|
|
8
|
-
city: {
|
|
9
|
-
description: '城市名称',
|
|
10
|
-
type: 'string',
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
required: ['city'],
|
|
14
|
-
type: 'object',
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const getWeather: PluginItem = {
|
|
19
|
-
avatar: '☂️',
|
|
20
|
-
name: 'realtimeWeather',
|
|
21
|
-
schema,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default getWeather;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export interface WeatherParams {
|
|
2
|
-
city: string;
|
|
3
|
-
extensions?: 'base' | 'all';
|
|
4
|
-
}
|
|
5
|
-
export type WeatherResult = Forecast[];
|
|
6
|
-
|
|
7
|
-
export interface Response {
|
|
8
|
-
count: string;
|
|
9
|
-
forecasts: Forecast[];
|
|
10
|
-
info: string;
|
|
11
|
-
infocode: string;
|
|
12
|
-
status: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface Forecast {
|
|
16
|
-
adcode: string;
|
|
17
|
-
casts: Cast[];
|
|
18
|
-
city: string;
|
|
19
|
-
province: string;
|
|
20
|
-
reporttime: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface Cast {
|
|
24
|
-
date: string;
|
|
25
|
-
daypower: string;
|
|
26
|
-
daytemp: string;
|
|
27
|
-
daytemp_float: string;
|
|
28
|
-
dayweather: string;
|
|
29
|
-
daywind: string;
|
|
30
|
-
nightpower: string;
|
|
31
|
-
nighttemp: string;
|
|
32
|
-
nighttemp_float: string;
|
|
33
|
-
nightweather: string;
|
|
34
|
-
nightwind: string;
|
|
35
|
-
week: string;
|
|
36
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { PluginItem } from '@/plugins/type';
|
|
2
|
-
|
|
3
|
-
const schema = {
|
|
4
|
-
description: '提取网页内容并总结',
|
|
5
|
-
name: 'websiteCrawler',
|
|
6
|
-
parameters: {
|
|
7
|
-
properties: {
|
|
8
|
-
url: {
|
|
9
|
-
description: '网页内容',
|
|
10
|
-
type: 'string',
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
required: ['url'],
|
|
14
|
-
type: 'object',
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const getWeather: PluginItem = { avatar: '🕸', name: 'websiteCrawler', schema };
|
|
19
|
-
|
|
20
|
-
export default getWeather;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export type Result = {
|
|
2
|
-
content: string;
|
|
3
|
-
title?: string;
|
|
4
|
-
url: string;
|
|
5
|
-
website?: string;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export interface ParserResponse {
|
|
9
|
-
/** author metadata */
|
|
10
|
-
byline: string;
|
|
11
|
-
|
|
12
|
-
/** HTML string of processed article content */
|
|
13
|
-
content: string;
|
|
14
|
-
|
|
15
|
-
/** content direction */
|
|
16
|
-
dir: string;
|
|
17
|
-
|
|
18
|
-
/** article description, or short excerpt from the content */
|
|
19
|
-
excerpt: string;
|
|
20
|
-
|
|
21
|
-
/** content language */
|
|
22
|
-
lang: string;
|
|
23
|
-
|
|
24
|
-
/** length of an article, in characters */
|
|
25
|
-
length: number;
|
|
26
|
-
|
|
27
|
-
/** name of the site */
|
|
28
|
-
siteName: string;
|
|
29
|
-
|
|
30
|
-
/** text content of the article, with all the HTML tags removed */
|
|
31
|
-
textContent: string;
|
|
32
|
-
|
|
33
|
-
/** article title */
|
|
34
|
-
title: string;
|
|
35
|
-
}
|