@lobehub/chat 0.25.0 → 0.26.1
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 +2 -1
- package/CHANGELOG.md +113 -6
- package/package.json +2 -5
- package/src/config/server.ts +22 -0
- package/src/const/fetch.ts +2 -2
- package/src/const/message.ts +2 -0
- package/src/locales/create.ts +3 -14
- package/src/locales/default/common.ts +4 -0
- package/src/locales/default/error.ts +27 -0
- package/src/locales/default/plugin.ts +19 -1
- package/src/locales/resources/zh_CN.ts +2 -0
- package/src/pages/api/auth.ts +25 -0
- package/src/pages/api/error.ts +21 -0
- package/src/pages/api/openai.api.ts +11 -5
- package/src/pages/api/openai.ts +24 -9
- package/src/pages/api/plugins.api.ts +11 -36
- package/src/pages/chat/[id]/Conversation/ChatList/Error/ApiKeyForm.tsx +40 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/ErrorActionContainer.tsx +23 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/InvalidAccess.tsx +76 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/OpenAiBizError.tsx +52 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Error/style.tsx +44 -0
- package/src/pages/chat/[id]/Conversation/{MessageExtra.tsx → ChatList/MessageExtra.tsx} +28 -26
- package/src/pages/chat/[id]/Conversation/ChatList/OTPInput.tsx +142 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/FunctionCall.tsx +60 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/PluginMessage.tsx +45 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/PluginResultRender.tsx +51 -0
- package/src/pages/chat/[id]/Conversation/ChatList/Plugins/style.ts +25 -0
- package/src/pages/chat/[id]/Conversation/ChatList/index.tsx +112 -0
- package/src/pages/chat/[id]/Conversation/Input/Token.tsx +1 -1
- package/src/pages/chat/[id]/edit/AgentPlugin/index.tsx +2 -2
- package/src/pages/setting/Header.tsx +2 -2
- package/src/pages/setting/index.page.tsx +11 -28
- package/src/pages/setting/layout.tsx +35 -0
- package/src/plugins/Render.ts +8 -0
- package/src/plugins/index.ts +7 -3
- package/src/plugins/searchEngine/index.ts +4 -1
- package/src/plugins/searchEngine/runner.ts +5 -73
- package/src/plugins/searchEngine/type.ts +80 -0
- package/src/plugins/type.ts +17 -0
- package/src/plugins/weather/Render.tsx +53 -0
- package/src/plugins/weather/index.ts +9 -1
- package/src/plugins/weather/runner.ts +12 -7
- package/src/plugins/weather/type.ts +36 -0
- package/src/plugins/webCrawler/index.ts +4 -1
- package/src/plugins/webCrawler/runner.ts +3 -27
- package/src/plugins/webCrawler/type.ts +32 -0
- package/src/services/chatModel.ts +3 -3
- package/src/services/plugin.ts +30 -0
- package/src/store/session/slices/chat/actions/message.ts +61 -42
- package/src/store/session/slices/chat/initialState.ts +2 -4
- package/src/store/session/slices/chat/selectors/utils.test.ts +3 -2
- package/src/store/session/slices/chat/selectors/utils.ts +4 -3
- package/src/types/chatMessage.ts +9 -6
- package/src/types/fetch.ts +26 -0
- package/src/types/openai.ts +3 -0
- package/src/types/plugin.ts +4 -0
- package/src/utils/fetch.ts +21 -25
- package/src/utils/message.ts +16 -0
- package/src/pages/chat/[id]/Conversation/ChatList.tsx +0 -69
- package/src/pages/chat/[id]/Conversation/FunctionMessage.tsx +0 -31
|
@@ -1,39 +1,22 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { memo, useEffect } from 'react';
|
|
3
|
-
import { useTranslation } from 'react-i18next';
|
|
1
|
+
import { memo } from 'react';
|
|
4
2
|
import { Flexbox } from 'react-layout-kit';
|
|
5
3
|
|
|
6
4
|
import HeaderSpacing from '@/components/HeaderSpacing';
|
|
7
|
-
import { createI18nNext } from '@/locales/create';
|
|
8
|
-
import ChatLayout from '@/pages/chat/layout';
|
|
9
|
-
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
10
5
|
|
|
11
6
|
import Header from './Header';
|
|
12
7
|
import SettingForm from './SettingForm';
|
|
8
|
+
import SettingLayout from './layout';
|
|
13
9
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
const SettingLayout = memo(() => {
|
|
17
|
-
const { t } = useTranslation('setting');
|
|
18
|
-
const pageTitle = genSiteHeadTitle(t('header.global'));
|
|
19
|
-
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
initI18n.finally();
|
|
22
|
-
}, []);
|
|
10
|
+
const Setting = memo(() => {
|
|
23
11
|
return (
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<HeaderSpacing />
|
|
32
|
-
<SettingForm />
|
|
33
|
-
</Flexbox>
|
|
34
|
-
</ChatLayout>
|
|
35
|
-
</>
|
|
12
|
+
<SettingLayout>
|
|
13
|
+
<Header />
|
|
14
|
+
<Flexbox align={'center'} flex={1} padding={24} style={{ overflow: 'auto' }}>
|
|
15
|
+
<HeaderSpacing />
|
|
16
|
+
<SettingForm />
|
|
17
|
+
</Flexbox>
|
|
18
|
+
</SettingLayout>
|
|
36
19
|
);
|
|
37
20
|
});
|
|
38
21
|
|
|
39
|
-
export default
|
|
22
|
+
export default Setting;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Head from 'next/head';
|
|
2
|
+
import { ReactNode, memo, useEffect } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
5
|
+
|
|
6
|
+
import SideBar from '@/features/SideBar';
|
|
7
|
+
import { createI18nNext } from '@/locales/create';
|
|
8
|
+
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
9
|
+
|
|
10
|
+
const initI18n = createI18nNext('setting');
|
|
11
|
+
|
|
12
|
+
const SettingLayout = memo<{ children: ReactNode }>(({ children }) => {
|
|
13
|
+
const { t } = useTranslation('setting');
|
|
14
|
+
const pageTitle = genSiteHeadTitle(t('header.global'));
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
initI18n.finally();
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<>
|
|
22
|
+
<Head>
|
|
23
|
+
<title>{pageTitle}</title>
|
|
24
|
+
</Head>
|
|
25
|
+
<Flexbox horizontal width={'100%'}>
|
|
26
|
+
<SideBar />
|
|
27
|
+
<Flexbox flex={1} height={'100vh'} style={{ position: 'relative' }}>
|
|
28
|
+
{children}
|
|
29
|
+
</Flexbox>
|
|
30
|
+
</Flexbox>
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export default SettingLayout;
|
package/src/plugins/index.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import type { PluginItem } from '@/plugins/type';
|
|
2
|
+
|
|
1
3
|
import searchEngine from './searchEngine';
|
|
2
4
|
import getWeather from './weather';
|
|
3
5
|
import webCrawler from './webCrawler';
|
|
4
6
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
export const PluginsMap: Record<string, PluginItem> = {
|
|
8
|
+
[getWeather.name]: getWeather,
|
|
9
|
+
[searchEngine.name]: searchEngine,
|
|
10
|
+
[webCrawler.name]: webCrawler,
|
|
11
|
+
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ChatCompletionFunctions } from 'openai-edge/types/api';
|
|
2
2
|
|
|
3
|
+
import { PluginItem } from '@/plugins/type';
|
|
4
|
+
|
|
3
5
|
import runner from './runner';
|
|
6
|
+
import { Result } from './type';
|
|
4
7
|
|
|
5
8
|
const schema: ChatCompletionFunctions = {
|
|
6
9
|
description: '查询搜索引擎获取信息',
|
|
@@ -17,7 +20,7 @@ const schema: ChatCompletionFunctions = {
|
|
|
17
20
|
},
|
|
18
21
|
};
|
|
19
22
|
|
|
20
|
-
const searchEngine = {
|
|
23
|
+
const searchEngine: PluginItem<Result> = {
|
|
21
24
|
avatar: '🔍',
|
|
22
25
|
name: 'searchEngine',
|
|
23
26
|
runner,
|
|
@@ -1,82 +1,14 @@
|
|
|
1
1
|
import querystring from 'query-string';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const API_KEY = process.env.SERPAI_API_KEY;
|
|
6
|
-
|
|
7
|
-
export type OrganicResults = OrganicResult[];
|
|
8
|
-
|
|
9
|
-
export interface OrganicResult {
|
|
10
|
-
about_page_link: string;
|
|
11
|
-
about_page_serpapi_link: string;
|
|
12
|
-
about_this_result: AboutThisResult;
|
|
13
|
-
cached_page_link?: string;
|
|
14
|
-
date?: string;
|
|
15
|
-
displayed_link: string;
|
|
16
|
-
favicon?: string;
|
|
17
|
-
link: string;
|
|
18
|
-
position: number;
|
|
19
|
-
related_results?: RelatedResult[];
|
|
20
|
-
rich_snippet?: RichSnippet;
|
|
21
|
-
snippet: string;
|
|
22
|
-
snippet_highlighted_words?: string[];
|
|
23
|
-
source: string;
|
|
24
|
-
thumbnail?: string;
|
|
25
|
-
title: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface AboutThisResult {
|
|
29
|
-
languages: string[];
|
|
30
|
-
regions: string[];
|
|
31
|
-
source: Source;
|
|
32
|
-
}
|
|
3
|
+
import { PluginRunner } from '@/plugins/type';
|
|
33
4
|
|
|
34
|
-
|
|
35
|
-
description: string;
|
|
36
|
-
icon: string;
|
|
37
|
-
security?: string;
|
|
38
|
-
source_info_link?: string;
|
|
39
|
-
}
|
|
5
|
+
import { OrganicResults, Result } from './type';
|
|
40
6
|
|
|
41
|
-
|
|
42
|
-
about_page_link: string;
|
|
43
|
-
about_page_serpapi_link: string;
|
|
44
|
-
about_this_result: AboutThisResult2;
|
|
45
|
-
cached_page_link: string;
|
|
46
|
-
date: string;
|
|
47
|
-
displayed_link: string;
|
|
48
|
-
link: string;
|
|
49
|
-
position: number;
|
|
50
|
-
snippet: string;
|
|
51
|
-
snippet_highlighted_words: string[];
|
|
52
|
-
title: string;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export interface AboutThisResult2 {
|
|
56
|
-
languages: string[];
|
|
57
|
-
regions: string[];
|
|
58
|
-
source: Source2;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface Source2 {
|
|
62
|
-
description: string;
|
|
63
|
-
icon: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface RichSnippet {
|
|
67
|
-
top: Top;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface Top {
|
|
71
|
-
detected_extensions: DetectedExtensions;
|
|
72
|
-
extensions: string[];
|
|
73
|
-
}
|
|
7
|
+
const BASE_URL = 'https://serpapi.com/search';
|
|
74
8
|
|
|
75
|
-
|
|
76
|
-
month_ago: number;
|
|
77
|
-
}
|
|
9
|
+
const API_KEY = process.env.SERPAI_API_KEY;
|
|
78
10
|
|
|
79
|
-
const fetchResult
|
|
11
|
+
const fetchResult: PluginRunner<{ keywords: string }, Result> = async ({ keywords }) => {
|
|
80
12
|
const params = {
|
|
81
13
|
api_key: API_KEY,
|
|
82
14
|
engine: 'google',
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export type OrganicResults = OrganicResult[];
|
|
2
|
+
|
|
3
|
+
export interface SearchItem {
|
|
4
|
+
content?: string;
|
|
5
|
+
date?: string;
|
|
6
|
+
link?: string;
|
|
7
|
+
source?: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
}
|
|
10
|
+
export type Result = SearchItem[];
|
|
11
|
+
|
|
12
|
+
interface OrganicResult {
|
|
13
|
+
about_page_link: string;
|
|
14
|
+
about_page_serpapi_link: string;
|
|
15
|
+
about_this_result: AboutThisResult;
|
|
16
|
+
cached_page_link?: string;
|
|
17
|
+
date?: string;
|
|
18
|
+
displayed_link: string;
|
|
19
|
+
favicon?: string;
|
|
20
|
+
link: string;
|
|
21
|
+
position: number;
|
|
22
|
+
related_results?: RelatedResult[];
|
|
23
|
+
rich_snippet?: RichSnippet;
|
|
24
|
+
snippet: string;
|
|
25
|
+
snippet_highlighted_words?: string[];
|
|
26
|
+
source: string;
|
|
27
|
+
thumbnail?: string;
|
|
28
|
+
title: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface AboutThisResult {
|
|
32
|
+
languages: string[];
|
|
33
|
+
regions: string[];
|
|
34
|
+
source: Source;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface Source {
|
|
38
|
+
description: string;
|
|
39
|
+
icon: string;
|
|
40
|
+
security?: string;
|
|
41
|
+
source_info_link?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface RelatedResult {
|
|
45
|
+
about_page_link: string;
|
|
46
|
+
about_page_serpapi_link: string;
|
|
47
|
+
about_this_result: AboutThisResult2;
|
|
48
|
+
cached_page_link: string;
|
|
49
|
+
date: string;
|
|
50
|
+
displayed_link: string;
|
|
51
|
+
link: string;
|
|
52
|
+
position: number;
|
|
53
|
+
snippet: string;
|
|
54
|
+
snippet_highlighted_words: string[];
|
|
55
|
+
title: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface AboutThisResult2 {
|
|
59
|
+
languages: string[];
|
|
60
|
+
regions: string[];
|
|
61
|
+
source: Source2;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface Source2 {
|
|
65
|
+
description: string;
|
|
66
|
+
icon: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface RichSnippet {
|
|
70
|
+
top: Top;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface Top {
|
|
74
|
+
detected_extensions: DetectedExtensions;
|
|
75
|
+
extensions: string[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface DetectedExtensions {
|
|
79
|
+
month_ago: number;
|
|
80
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ChatCompletionFunctions } from 'openai-edge/types/api';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface PluginItem<Result = any, RunnerParams = any> {
|
|
5
|
+
avatar: string;
|
|
6
|
+
name: string;
|
|
7
|
+
runner: PluginRunner<RunnerParams, Result>;
|
|
8
|
+
schema: ChatCompletionFunctions;
|
|
9
|
+
}
|
|
10
|
+
export type PluginRender = (props: PluginRenderProps) => ReactNode;
|
|
11
|
+
|
|
12
|
+
export type PluginRunner<Params = object, Result = any> = (params: Params) => Promise<Result>;
|
|
13
|
+
|
|
14
|
+
export interface PluginRenderProps<Result = any> {
|
|
15
|
+
content: Result;
|
|
16
|
+
name: string;
|
|
17
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
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,3 +1,6 @@
|
|
|
1
|
+
import { PluginItem } from '@/plugins/type';
|
|
2
|
+
import { WeatherResult } from '@/plugins/weather/type';
|
|
3
|
+
|
|
1
4
|
import runner from './runner';
|
|
2
5
|
|
|
3
6
|
const schema = {
|
|
@@ -15,6 +18,11 @@ const schema = {
|
|
|
15
18
|
},
|
|
16
19
|
};
|
|
17
20
|
|
|
18
|
-
const getWeather = {
|
|
21
|
+
const getWeather: PluginItem<WeatherResult> = {
|
|
22
|
+
avatar: '☂️',
|
|
23
|
+
name: 'realtimeWeather',
|
|
24
|
+
runner,
|
|
25
|
+
schema,
|
|
26
|
+
};
|
|
19
27
|
|
|
20
28
|
export default getWeather;
|
|
@@ -1,30 +1,35 @@
|
|
|
1
|
+
import { PluginRunner } from '@/plugins/type';
|
|
2
|
+
|
|
3
|
+
import { Response, WeatherParams, WeatherResult } from './type';
|
|
4
|
+
|
|
1
5
|
const weatherBaseURL = 'https://restapi.amap.com/v3/weather/weatherInfo';
|
|
2
6
|
|
|
3
7
|
const citySearchURL = 'https://restapi.amap.com/v3/config/district';
|
|
4
8
|
|
|
5
9
|
const KEY = process.env.GAODE_WEATHER_KEY;
|
|
6
10
|
|
|
7
|
-
interface WeatherParams {
|
|
8
|
-
city: string;
|
|
9
|
-
extensions?: 'base' | 'all';
|
|
10
|
-
}
|
|
11
|
-
|
|
12
11
|
const fetchCityCode = async (keywords: string): Promise<string> => {
|
|
13
12
|
const URL = `${citySearchURL}?keywords=${keywords}&subdistrict=0&extensions=base&key=${KEY}`;
|
|
14
13
|
const res = await fetch(URL);
|
|
15
14
|
|
|
16
15
|
const data = await res.json();
|
|
16
|
+
console.log(data);
|
|
17
17
|
|
|
18
18
|
return data.districts[0].adcode;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
const fetchWeather
|
|
21
|
+
const fetchWeather: PluginRunner<WeatherParams, WeatherResult> = async ({
|
|
22
|
+
city,
|
|
23
|
+
extensions = 'all',
|
|
24
|
+
}) => {
|
|
22
25
|
const cityCode = await fetchCityCode(city);
|
|
23
26
|
|
|
24
27
|
const URL = `${weatherBaseURL}?city=${cityCode}&extensions=${extensions}&key=${KEY}`;
|
|
25
28
|
const res = await fetch(URL);
|
|
26
29
|
|
|
27
|
-
|
|
30
|
+
const data: Response = await res.json();
|
|
31
|
+
|
|
32
|
+
return data.forecasts;
|
|
28
33
|
};
|
|
29
34
|
|
|
30
35
|
export default fetchWeather;
|
|
@@ -0,0 +1,36 @@
|
|
|
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,4 +1,7 @@
|
|
|
1
|
+
import { PluginItem } from '@/plugins/type';
|
|
2
|
+
|
|
1
3
|
import runner from './runner';
|
|
4
|
+
import { Result } from './type';
|
|
2
5
|
|
|
3
6
|
const schema = {
|
|
4
7
|
description: '提取网页内容并总结',
|
|
@@ -15,6 +18,6 @@ const schema = {
|
|
|
15
18
|
},
|
|
16
19
|
};
|
|
17
20
|
|
|
18
|
-
const getWeather = { avatar: '🕸', name: 'websiteCrawler', runner, schema };
|
|
21
|
+
const getWeather: PluginItem<Result> = { avatar: '🕸', name: 'websiteCrawler', runner, schema };
|
|
19
22
|
|
|
20
23
|
export default getWeather;
|
|
@@ -1,36 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import { PluginRunner } from '@/plugins/type';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
crawl: Crawl;
|
|
5
|
-
markdown: string;
|
|
6
|
-
metadata: Metadata;
|
|
7
|
-
screenshotUrl: any;
|
|
8
|
-
text: string;
|
|
9
|
-
url: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface Crawl {
|
|
13
|
-
depth: number;
|
|
14
|
-
httpStatusCode: number;
|
|
15
|
-
loadedTime: string;
|
|
16
|
-
loadedUrl: string;
|
|
17
|
-
referrerUrl: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface Metadata {
|
|
21
|
-
author: any;
|
|
22
|
-
canonicalUrl: string;
|
|
23
|
-
description: string;
|
|
24
|
-
keywords: string;
|
|
25
|
-
languageCode: string;
|
|
26
|
-
title: string;
|
|
27
|
-
}
|
|
3
|
+
import { DataResults, Result } from './type';
|
|
28
4
|
|
|
29
5
|
const BASE_URL =
|
|
30
6
|
'https://api.apify.com/v2/acts/apify~website-content-crawler/run-sync-get-dataset-items';
|
|
31
7
|
const token = process.env.APIFY_API_KEY;
|
|
32
8
|
|
|
33
|
-
const runner
|
|
9
|
+
const runner: PluginRunner<{ url: string }, Result> = async ({ url }) => {
|
|
34
10
|
// Prepare Actor input
|
|
35
11
|
const input = {
|
|
36
12
|
aggressivePrune: false,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type DataResults = DataItem[];
|
|
2
|
+
|
|
3
|
+
export type Result = {
|
|
4
|
+
content?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
url?: string;
|
|
7
|
+
};
|
|
8
|
+
export interface DataItem {
|
|
9
|
+
crawl: Crawl;
|
|
10
|
+
markdown: string;
|
|
11
|
+
metadata: Metadata;
|
|
12
|
+
screenshotUrl: any;
|
|
13
|
+
text: string;
|
|
14
|
+
url: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface Crawl {
|
|
18
|
+
depth: number;
|
|
19
|
+
httpStatusCode: number;
|
|
20
|
+
loadedTime: string;
|
|
21
|
+
loadedUrl: string;
|
|
22
|
+
referrerUrl: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Metadata {
|
|
26
|
+
author: any;
|
|
27
|
+
canonicalUrl: string;
|
|
28
|
+
description: string;
|
|
29
|
+
keywords: string;
|
|
30
|
+
languageCode: string;
|
|
31
|
+
title: string;
|
|
32
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { merge } from 'lodash-es';
|
|
2
2
|
|
|
3
|
-
import { OPENAI_API_KEY_HEADER_KEY } from '@/const/fetch';
|
|
3
|
+
import { LOBE_CHAT_ACCESS_CODE, OPENAI_API_KEY_HEADER_KEY } from '@/const/fetch';
|
|
4
4
|
import { initialLobeAgentConfig } from '@/store/session';
|
|
5
5
|
import { useSettings } from '@/store/settings';
|
|
6
6
|
import type { OpenAIStreamPayload } from '@/types/openai';
|
|
@@ -9,7 +9,6 @@ import { URLS } from './url';
|
|
|
9
9
|
|
|
10
10
|
interface FetchChatModelOptions {
|
|
11
11
|
signal?: AbortSignal | undefined;
|
|
12
|
-
withPlugin?: boolean;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
/**
|
|
@@ -28,10 +27,11 @@ export const fetchChatModel = (
|
|
|
28
27
|
params,
|
|
29
28
|
);
|
|
30
29
|
|
|
31
|
-
return fetch(
|
|
30
|
+
return fetch(URLS.openai, {
|
|
32
31
|
body: JSON.stringify(payload),
|
|
33
32
|
headers: {
|
|
34
33
|
'Content-Type': 'application/json',
|
|
34
|
+
[LOBE_CHAT_ACCESS_CODE]: useSettings.getState().settings.password || '',
|
|
35
35
|
[OPENAI_API_KEY_HEADER_KEY]: useSettings.getState().settings.OPENAI_API_KEY || '',
|
|
36
36
|
},
|
|
37
37
|
method: 'POST',
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { LOBE_CHAT_ACCESS_CODE } from '@/const/fetch';
|
|
2
|
+
import { useSettings } from '@/store/settings';
|
|
3
|
+
import { OpenAIPluginPayload } from '@/types/plugin';
|
|
4
|
+
|
|
5
|
+
import { URLS } from './url';
|
|
6
|
+
|
|
7
|
+
interface FetchChatModelOptions {
|
|
8
|
+
signal?: AbortSignal | undefined;
|
|
9
|
+
withPlugin?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 专门用于对话的 fetch
|
|
14
|
+
*/
|
|
15
|
+
export const fetchPlugin = async (
|
|
16
|
+
params: Partial<OpenAIPluginPayload>,
|
|
17
|
+
options?: FetchChatModelOptions,
|
|
18
|
+
) => {
|
|
19
|
+
const res = await fetch(URLS.plugins, {
|
|
20
|
+
body: JSON.stringify(params),
|
|
21
|
+
headers: {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
[LOBE_CHAT_ACCESS_CODE]: useSettings.getState().settings.password || '',
|
|
24
|
+
},
|
|
25
|
+
method: 'POST',
|
|
26
|
+
signal: options?.signal,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
return await res.text();
|
|
30
|
+
};
|