@lobehub/chat 0.73.0 → 0.75.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/.github/workflows/contributor-help.yml +1 -1
- package/.github/workflows/sync.yml +43 -0
- package/.github/workflows/wiki-sync.yml +1 -0
- package/CHANGELOG.md +87 -0
- package/README.md +40 -6
- package/{README-zh_CN.md → README.zh-CN.md} +38 -4
- package/docs/Home.md +6 -0
- package/docs/Upstream-Sync.en-US.md +16 -0
- package/docs/Upstream-Sync.zh-CN.md +16 -0
- package/docs/_Sidebar.md +6 -0
- package/locales/en_US/market.json +12 -0
- package/locales/en_US/plugin.json +11 -2
- package/locales/en_US/setting.json +63 -2
- package/locales/ru_RU/market.json +12 -0
- package/locales/ru_RU/plugin.json +44 -49
- package/locales/ru_RU/setting.json +63 -2
- package/locales/zh_CN/common.json +1 -1
- package/locales/zh_CN/market.json +12 -0
- package/locales/zh_CN/plugin.json +19 -5
- package/locales/zh_CN/setting.json +62 -14
- package/package.json +5 -4
- package/scripts/i18nWorkflow/const.ts +19 -0
- package/scripts/i18nWorkflow/genDefaultLocale.ts +19 -0
- package/scripts/i18nWorkflow/genDiff.ts +50 -0
- package/scripts/i18nWorkflow/genResources.ts +26 -0
- package/scripts/i18nWorkflow/index.ts +15 -0
- package/scripts/i18nWorkflow/utils.ts +85 -0
- package/src/const/layoutTokens.ts +3 -1
- package/src/const/market.ts +15 -0
- package/src/const/url.ts +29 -4
- package/src/features/AgentSetting/AgentConfig/index.tsx +1 -2
- package/src/features/AgentSetting/AgentPlugin/MarketSettingModal.tsx +1 -1
- package/src/features/AgentSetting/store/initialState.ts +1 -1
- package/src/features/MobileTabBar/index.tsx +2 -2
- package/src/features/SideBar/TopActions.tsx +2 -2
- package/src/locales/default/market.ts +12 -0
- package/src/locales/resources/en_US.ts +2 -0
- package/src/locales/resources/ru_RU.ts +2 -0
- package/src/locales/resources/zh_CN.ts +2 -0
- package/src/pages/chat/features/Conversation/Input/{Action.tsx → ActionBar/ActionLeft.tsx} +2 -2
- package/src/pages/chat/features/Conversation/Input/ActionBar/ActionRight.tsx +36 -0
- package/src/pages/chat/features/Conversation/Input/Desktop.tsx +40 -0
- package/src/pages/chat/features/Conversation/Input/Footer/SaveTopic.tsx +27 -0
- package/src/pages/chat/features/Conversation/Input/Footer/index.tsx +35 -0
- package/src/pages/chat/features/Conversation/Input/Mobile.tsx +12 -0
- package/src/pages/chat/features/Conversation/Input/index.tsx +20 -38
- package/src/pages/chat/features/SessionList/Header/Desktop.tsx +6 -13
- package/src/pages/chat/features/SessionList/Header/Mobile.tsx +1 -1
- package/src/pages/chat/features/SessionList/List/AddButton.tsx +1 -1
- package/src/pages/chat/features/SessionList/List/Item/index.tsx +4 -3
- package/src/pages/chat/features/SessionList/List/index.tsx +1 -3
- package/src/pages/chat/features/SessionList/Mobile.tsx +2 -12
- package/src/pages/chat/features/SessionSearchBar/index.tsx +26 -0
- package/src/pages/chat/features/Sidebar/Topic/index.tsx +18 -6
- package/src/pages/chat/features/Sidebar/TopicSearchBar/index.tsx +24 -0
- package/src/pages/chat/features/Sidebar/index.tsx +2 -9
- package/src/pages/market/features/AgentCard/AgentCardBanner.tsx +64 -0
- package/src/pages/market/features/AgentCard/AgentCardItem.tsx +57 -0
- package/src/pages/market/features/AgentCard/Loading.tsx +13 -0
- package/src/pages/market/features/AgentCard/index.tsx +37 -0
- package/src/pages/market/features/AgentCard/style.ts +22 -0
- package/src/pages/market/features/AgentSearchBar/index.tsx +26 -0
- package/src/pages/market/features/Header/Desktop.tsx +15 -4
- package/src/pages/market/features/Header/Mobile.tsx +7 -24
- package/src/pages/market/features/SideBar/AgentInfo/Comment.tsx +16 -0
- package/src/pages/market/features/SideBar/AgentInfo/Header.tsx +68 -0
- package/src/pages/market/features/SideBar/AgentInfo/Loading.tsx +61 -0
- package/src/pages/market/features/SideBar/AgentInfo/TokenTag.tsx +25 -0
- package/src/pages/market/features/SideBar/AgentInfo/index.tsx +68 -0
- package/src/pages/market/features/SideBar/AgentInfo/style.ts +46 -0
- package/src/pages/market/features/SideBar/Desktop.tsx +70 -0
- package/src/pages/market/features/SideBar/Mobile.tsx +36 -0
- package/src/pages/market/features/SideBar/index.tsx +23 -0
- package/src/pages/market/features/TagList/index.tsx +29 -0
- package/src/pages/market/index.page.tsx +11 -2
- package/src/pages/market/layout.mobile.tsx +8 -7
- package/src/pages/market/layout.tsx +39 -1
- package/src/pages/settings/features/Header/Desktop.tsx +2 -4
- package/src/pages/settings/features/Header/Mobile.tsx +1 -1
- package/src/pages/settings/features/Settings/Common.tsx +1 -2
- package/src/pages/settings/features/Settings/index.tsx +17 -4
- package/src/services/agentMarket.ts +21 -0
- package/src/store/global/initialState.ts +1 -2
- package/src/store/market/action.ts +57 -0
- package/src/store/market/index.ts +3 -0
- package/src/store/market/initialState.ts +17 -0
- package/src/store/market/selectors.ts +36 -0
- package/src/store/market/store.ts +51 -0
- package/src/store/session/slices/session/action.ts +5 -3
- package/src/store/session/slices/session/initialState.ts +2 -0
- package/src/store/session/slices/session/reducers/session.test.ts +4 -4
- package/src/types/market.ts +19 -0
- package/src/types/meta.ts +1 -1
- package/src/utils/filter.ts +1 -1
- package/src/utils/findDuplicates.ts +22 -0
- package/scripts/genDefaultLocale.ts +0 -18
- package/scripts/genResources.ts +0 -51
- package/scripts/toc.ts +0 -7
- package/src/components/Empty/index.tsx +0 -63
- package/src/components/Empty/style.ts +0 -31
- package/src/components/SelectWithImg/index.tsx +0 -97
- package/src/components/SelectWithImg/styles.ts +0 -43
- package/src/pages/chat/features/Conversation/Input/ActionRight.tsx +0 -31
- package/src/pages/chat/features/Conversation/Input/Footer.tsx +0 -49
- /package/src/components/{ManifestPreviewer.tsx → ManifestPreviewer/index.tsx} +0 -0
- /package/src/pages/chat/features/Conversation/Input/{Token.tsx → ActionBar/Token.tsx} +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { consola } from 'consola';
|
|
2
|
+
import { colors } from 'consola/utils';
|
|
3
|
+
import { tocForResources } from 'i18next-resources-for-ts';
|
|
4
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
|
|
7
|
+
import i18nConfig from '../../.i18nrc';
|
|
8
|
+
import { srcLocalesResources } from './const';
|
|
9
|
+
|
|
10
|
+
export const readJSON = (filePath: string) => {
|
|
11
|
+
const data = readFileSync(filePath, 'utf8');
|
|
12
|
+
return JSON.parse(data);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const writeJSON = (filePath: string, data: any) => {
|
|
16
|
+
const jsonStr = JSON.stringify(data, null, 2);
|
|
17
|
+
writeFileSync(filePath, jsonStr, 'utf8');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const genResourcesContent = (locales: string[]) => {
|
|
21
|
+
let index = '';
|
|
22
|
+
let indexObj = '';
|
|
23
|
+
|
|
24
|
+
for (const locale of locales) {
|
|
25
|
+
index += `import ${locale} from "./${locale}";\n`;
|
|
26
|
+
indexObj += ` "${locale.replace('_', '-')}": ${locale},\n`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return `${index}
|
|
30
|
+
const resources = {
|
|
31
|
+
${indexObj}} as const;
|
|
32
|
+
export default resources;
|
|
33
|
+
export const defaultResources = ${i18nConfig.entryLocale};
|
|
34
|
+
export type Resources = typeof resources;
|
|
35
|
+
export type DefaultResources = typeof defaultResources;
|
|
36
|
+
export type Namespaces = keyof DefaultResources;
|
|
37
|
+
export type Locales = keyof Resources;
|
|
38
|
+
`;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const genNamespaceList = (files: string[], locale: string) => {
|
|
42
|
+
return files.map((file) => ({
|
|
43
|
+
name: file.replace('.json', ''),
|
|
44
|
+
path: resolve(i18nConfig.output, locale, file),
|
|
45
|
+
}));
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const genToc = (files: string[], locale: string) => {
|
|
49
|
+
const ns = genNamespaceList(files, locale);
|
|
50
|
+
let toc = tocForResources(ns, srcLocalesResources).replaceAll('\\', '/');
|
|
51
|
+
if (locale === i18nConfig.entryLocale) {
|
|
52
|
+
toc = toc.replaceAll('.json', '').replaceAll('../../../locales/zh_CN', '../default');
|
|
53
|
+
}
|
|
54
|
+
return toc;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const diff = (obj1: any, obj2: any, prefix: string = ''): string[] => {
|
|
58
|
+
let result: string[] = [];
|
|
59
|
+
for (const key in obj1) {
|
|
60
|
+
if (!obj2[key]) continue;
|
|
61
|
+
if (typeof obj1[key] === 'object' && obj1[key] !== null && obj2[key]) {
|
|
62
|
+
result = result.concat(diff(obj1[key], obj2[key], `${key}.`));
|
|
63
|
+
} else if (obj1[key] !== obj2[key]) {
|
|
64
|
+
result.push(`${prefix}${key}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const unset = (obj: any, key: string) => {
|
|
71
|
+
const keys = key.split('.');
|
|
72
|
+
const lastKey = keys.pop();
|
|
73
|
+
const lastObj = keys.reduce((obj, key) => (obj[key] = obj[key] || {}), obj);
|
|
74
|
+
if (lastKey) delete lastObj[lastKey];
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const tagBlue = (text: string) => colors.bgBlueBright(colors.black(` ${text} `));
|
|
78
|
+
export const tagYellow = (text: string) => colors.bgYellowBright(colors.black(` ${text} `));
|
|
79
|
+
export const tagGreen = (text: string) => colors.bgGreenBright(colors.black(` ${text} `));
|
|
80
|
+
export const tagWhite = (text: string) => colors.bgWhiteBright(colors.black(` ${text} `));
|
|
81
|
+
|
|
82
|
+
export const split = (name: string) => {
|
|
83
|
+
consola.log('');
|
|
84
|
+
consola.log(colors.gray(`========================== ${name} ==============================`));
|
|
85
|
+
};
|
|
@@ -5,8 +5,10 @@ export const MOBILE_NABBAR_HEIGHT = 44;
|
|
|
5
5
|
export const MOBILE_TABBAR_HEIGHT = 48;
|
|
6
6
|
export const CHAT_TEXTAREA_HEIGHT = 200;
|
|
7
7
|
export const CHAT_SIDEBAR_WIDTH = 280;
|
|
8
|
+
export const MARKET_SIDEBAR_WIDTH = 400;
|
|
8
9
|
export const FOLDER_WIDTH = 256;
|
|
10
|
+
export const MAX_WIDTH = 1024;
|
|
9
11
|
export const FORM_STYLE: FormProps = {
|
|
10
12
|
itemMinWidth: 'max(30%,240px)',
|
|
11
|
-
style: { maxWidth:
|
|
13
|
+
style: { maxWidth: MAX_WIDTH, width: '100%' },
|
|
12
14
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DEFAULT_AGENT_CONFIG } from '@/const/settings';
|
|
2
|
+
import { AgentsMarketItem } from '@/types/market';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_AGENT_META } from './meta';
|
|
5
|
+
|
|
6
|
+
export const DEFAULT_AGENTS_MARKET_ITEM: AgentsMarketItem = {
|
|
7
|
+
author: '',
|
|
8
|
+
config: DEFAULT_AGENT_CONFIG,
|
|
9
|
+
createAt: Date.now().toString(),
|
|
10
|
+
homepage: '',
|
|
11
|
+
identifier: '',
|
|
12
|
+
manifest: '',
|
|
13
|
+
meta: DEFAULT_AGENT_META,
|
|
14
|
+
schemaVersion: 1,
|
|
15
|
+
};
|
package/src/const/url.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import urlJoin from 'url-join';
|
|
2
|
+
|
|
1
3
|
import { localeOptions } from '@/locales/options';
|
|
2
4
|
import { Locales } from '@/locales/resources';
|
|
3
5
|
|
|
@@ -11,15 +13,38 @@ export const FEEDBACK = pkg.bugs.url;
|
|
|
11
13
|
export const DISCORD = 'https://discord.gg/AYFPHvv2jT';
|
|
12
14
|
|
|
13
15
|
export const PLUGINS_INDEX_URL =
|
|
14
|
-
process.env.PLUGINS_INDEX_URL ?? 'https://chat-plugins.lobehub.com
|
|
16
|
+
process.env.PLUGINS_INDEX_URL ?? 'https://chat-plugins.lobehub.com';
|
|
17
|
+
|
|
18
|
+
export const DEFAULT_LANG = 'en-US';
|
|
15
19
|
|
|
16
|
-
export const
|
|
17
|
-
|
|
20
|
+
export const checkLang = (lang: Locales) => {
|
|
21
|
+
return lang === DEFAULT_LANG || !localeOptions.map((o) => o.value).includes(lang);
|
|
22
|
+
};
|
|
23
|
+
export const getPluginIndexJSON = (lang: Locales = DEFAULT_LANG, baseUrl = PLUGINS_INDEX_URL) => {
|
|
24
|
+
if (checkLang(lang)) return baseUrl;
|
|
18
25
|
|
|
19
|
-
return
|
|
26
|
+
return urlJoin(baseUrl, `index.${lang}.json`);
|
|
20
27
|
};
|
|
21
28
|
|
|
22
29
|
export const AGENTS_INDEX_URL = process.env.AGENTS_INDEX_URL ?? 'https://chat-agents.lobehub.com';
|
|
23
30
|
|
|
31
|
+
export const getAgentIndexJSON = (lang: Locales = DEFAULT_LANG, baseUrl = AGENTS_INDEX_URL) => {
|
|
32
|
+
if (checkLang(lang)) return baseUrl;
|
|
33
|
+
|
|
34
|
+
return urlJoin(baseUrl, `index.${lang}.json`);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const getAgentJSON = (
|
|
38
|
+
identifier: string,
|
|
39
|
+
lang: Locales = DEFAULT_LANG,
|
|
40
|
+
baseUrl = AGENTS_INDEX_URL,
|
|
41
|
+
) => {
|
|
42
|
+
if (checkLang(lang)) return urlJoin(baseUrl, `${identifier}.json`);
|
|
43
|
+
|
|
44
|
+
return urlJoin(baseUrl, `${identifier}.${lang}.json`);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const AGENTS_INDEX_GITHUB = 'https://github.com/lobehub/lobe-chat-agents';
|
|
48
|
+
|
|
24
49
|
export const SESSION_CHAT_URL = (id: string = INBOX_SESSION_ID, mobile?: boolean) =>
|
|
25
50
|
mobile ? `/chat/mobile#session=${id}` : `/chat#session=${id}`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Form, ItemGroup, SliderWithInput } from '@lobehub/ui';
|
|
1
|
+
import { Form, ItemGroup, SelectWithImg, SliderWithInput } from '@lobehub/ui';
|
|
2
2
|
import { ConfigProvider, Input, Select, Switch } from 'antd';
|
|
3
3
|
import { useTheme, useThemeMode } from 'antd-style';
|
|
4
4
|
import isEqual from 'fast-deep-equal';
|
|
@@ -7,7 +7,6 @@ import { BrainCog, LayoutList, MessageSquare, MessagesSquare } from 'lucide-reac
|
|
|
7
7
|
import { memo, useMemo } from 'react';
|
|
8
8
|
import { useTranslation } from 'react-i18next';
|
|
9
9
|
|
|
10
|
-
import SelectWithImg from '@/components/SelectWithImg';
|
|
11
10
|
import { FORM_STYLE } from '@/const/layoutTokens';
|
|
12
11
|
import { LanguageModel } from '@/types/llm';
|
|
13
12
|
import { LobeAgentConfigKeys } from '@/types/session';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Icon, MobileTabBar, type MobileTabBarProps } from '@lobehub/ui';
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
|
-
import {
|
|
3
|
+
import { Bot, MessageSquare } from 'lucide-react';
|
|
4
4
|
import Router from 'next/router';
|
|
5
5
|
import { rgba } from 'polished';
|
|
6
6
|
import { memo, useMemo } from 'react';
|
|
@@ -33,7 +33,7 @@ export default memo<{ className?: string }>(({ className }) => {
|
|
|
33
33
|
title: t('tab.chat'),
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
|
-
icon: (active) => <Icon className={active ? styles.active : undefined} icon={
|
|
36
|
+
icon: (active) => <Icon className={active ? styles.active : undefined} icon={Bot} />,
|
|
37
37
|
key: 'market',
|
|
38
38
|
onClick: () => {
|
|
39
39
|
Router.push({ hash: '', pathname: `/market` });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ActionIcon } from '@lobehub/ui';
|
|
2
|
-
import {
|
|
2
|
+
import { Bot, MessageSquare } from 'lucide-react';
|
|
3
3
|
import Router from 'next/router';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
@@ -32,7 +32,7 @@ const TopActions = memo<TopActionProps>(({ tab, setTab }) => {
|
|
|
32
32
|
/>
|
|
33
33
|
<ActionIcon
|
|
34
34
|
active={tab === 'market'}
|
|
35
|
-
icon={
|
|
35
|
+
icon={Bot}
|
|
36
36
|
onClick={() => {
|
|
37
37
|
if (Router.asPath.startsWith('/market')) return;
|
|
38
38
|
Router.push('/market');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import common from '../../../locales/en_US/common.json';
|
|
2
2
|
import empty from '../../../locales/en_US/empty.json';
|
|
3
3
|
import error from '../../../locales/en_US/error.json';
|
|
4
|
+
import market from '../../../locales/en_US/market.json';
|
|
4
5
|
import plugin from '../../../locales/en_US/plugin.json';
|
|
5
6
|
import setting from '../../../locales/en_US/setting.json';
|
|
6
7
|
import welcome from '../../../locales/en_US/welcome.json';
|
|
@@ -9,6 +10,7 @@ const resources = {
|
|
|
9
10
|
common,
|
|
10
11
|
empty,
|
|
11
12
|
error,
|
|
13
|
+
market,
|
|
12
14
|
plugin,
|
|
13
15
|
setting,
|
|
14
16
|
welcome,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import common from '../../../locales/ru_RU/common.json';
|
|
2
2
|
import empty from '../../../locales/ru_RU/empty.json';
|
|
3
3
|
import error from '../../../locales/ru_RU/error.json';
|
|
4
|
+
import market from '../../../locales/ru_RU/market.json';
|
|
4
5
|
import plugin from '../../../locales/ru_RU/plugin.json';
|
|
5
6
|
import setting from '../../../locales/ru_RU/setting.json';
|
|
6
7
|
import welcome from '../../../locales/ru_RU/welcome.json';
|
|
@@ -9,6 +10,7 @@ const resources = {
|
|
|
9
10
|
common,
|
|
10
11
|
empty,
|
|
11
12
|
error,
|
|
13
|
+
market,
|
|
12
14
|
plugin,
|
|
13
15
|
setting,
|
|
14
16
|
welcome,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import common from '../default/common';
|
|
2
2
|
import empty from '../default/empty';
|
|
3
3
|
import error from '../default/error';
|
|
4
|
+
import market from '../default/market';
|
|
4
5
|
import plugin from '../default/plugin';
|
|
5
6
|
import setting from '../default/setting';
|
|
6
7
|
import welcome from '../default/welcome';
|
|
@@ -9,6 +10,7 @@ const resources = {
|
|
|
9
10
|
common,
|
|
10
11
|
empty,
|
|
11
12
|
error,
|
|
13
|
+
market,
|
|
12
14
|
plugin,
|
|
13
15
|
setting,
|
|
14
16
|
welcome,
|
|
@@ -9,7 +9,7 @@ import { useSessionStore } from '@/store/session';
|
|
|
9
9
|
import { agentSelectors } from '@/store/session/selectors';
|
|
10
10
|
import { LanguageModel } from '@/types/llm';
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const ActionLeft = memo(() => {
|
|
13
13
|
const { t } = useTranslation('setting');
|
|
14
14
|
|
|
15
15
|
const [model, temperature, historyCount, unlimited, updateAgentConfig] = useSessionStore((s) => {
|
|
@@ -107,4 +107,4 @@ const InputActions = memo(() => {
|
|
|
107
107
|
);
|
|
108
108
|
});
|
|
109
109
|
|
|
110
|
-
export default
|
|
110
|
+
export default ActionLeft;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ActionIcon } from '@lobehub/ui';
|
|
2
|
+
import { Popconfirm } from 'antd';
|
|
3
|
+
import { Eraser } from 'lucide-react';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
import { useSessionStore } from '@/store/session';
|
|
8
|
+
|
|
9
|
+
import SaveTopic from '../Footer/SaveTopic';
|
|
10
|
+
|
|
11
|
+
const ActionsRight = memo(() => {
|
|
12
|
+
const { t } = useTranslation('setting');
|
|
13
|
+
const [clearMessage] = useSessionStore((s) => [s.clearMessage, s.updateAgentConfig]);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
<SaveTopic />
|
|
18
|
+
<Popconfirm
|
|
19
|
+
cancelText={t('cancel', { ns: 'common' })}
|
|
20
|
+
okButtonProps={{ danger: true }}
|
|
21
|
+
okText={t('ok', { ns: 'common' })}
|
|
22
|
+
onConfirm={() => clearMessage()}
|
|
23
|
+
placement={'topRight'}
|
|
24
|
+
title={t('confirmClearCurrentMessages', { ns: 'common' })}
|
|
25
|
+
>
|
|
26
|
+
<ActionIcon
|
|
27
|
+
icon={Eraser}
|
|
28
|
+
placement={'bottom'}
|
|
29
|
+
title={t('clearCurrentMessages', { ns: 'common' })}
|
|
30
|
+
/>
|
|
31
|
+
</Popconfirm>
|
|
32
|
+
</>
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default ActionsRight;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { DraggablePanel } from '@lobehub/ui';
|
|
2
|
+
import { ReactNode, memo } from 'react';
|
|
3
|
+
|
|
4
|
+
import { CHAT_TEXTAREA_HEIGHT, HEADER_HEIGHT } from '@/const/layoutTokens';
|
|
5
|
+
import { useGlobalStore } from '@/store/global';
|
|
6
|
+
|
|
7
|
+
interface ChatInputDesktopLayoutProps {
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
expand?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const ChatInputDesktopLayout = memo<ChatInputDesktopLayoutProps>(({ children, expand }) => {
|
|
13
|
+
const [inputHeight, updatePreference] = useGlobalStore((s) => [
|
|
14
|
+
s.preference.inputHeight,
|
|
15
|
+
s.updatePreference,
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<DraggablePanel
|
|
20
|
+
expandable={false}
|
|
21
|
+
fullscreen={expand}
|
|
22
|
+
headerHeight={HEADER_HEIGHT}
|
|
23
|
+
minHeight={CHAT_TEXTAREA_HEIGHT}
|
|
24
|
+
onSizeChange={(_, size) => {
|
|
25
|
+
if (!size) return;
|
|
26
|
+
|
|
27
|
+
updatePreference({
|
|
28
|
+
inputHeight: typeof size.height === 'string' ? Number.parseInt(size.height) : size.height,
|
|
29
|
+
});
|
|
30
|
+
}}
|
|
31
|
+
placement="bottom"
|
|
32
|
+
size={{ height: inputHeight, width: '100%' }}
|
|
33
|
+
style={{ zIndex: 10 }}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</DraggablePanel>
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export default ChatInputDesktopLayout;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ActionIcon, Icon, Tooltip } from '@lobehub/ui';
|
|
2
|
+
import { Button } from 'antd';
|
|
3
|
+
import { useResponsive } from 'antd-style';
|
|
4
|
+
import { LucideGalleryVerticalEnd } from 'lucide-react';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
|
|
8
|
+
import { useSessionStore } from '@/store/session';
|
|
9
|
+
|
|
10
|
+
const SaveTopic = memo(() => {
|
|
11
|
+
const { t } = useTranslation('common');
|
|
12
|
+
const [hasTopic, saveToTopic] = useSessionStore((s) => [!!s.activeTopicId, s.saveToTopic]);
|
|
13
|
+
const { mobile } = useResponsive();
|
|
14
|
+
|
|
15
|
+
if (hasTopic) return undefined;
|
|
16
|
+
|
|
17
|
+
const Render = mobile ? ActionIcon : Button;
|
|
18
|
+
const icon: any = mobile ? LucideGalleryVerticalEnd : <Icon icon={LucideGalleryVerticalEnd} />;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Tooltip title={t('topic.saveCurrentMessages')}>
|
|
22
|
+
<Render icon={icon} onClick={saveToTopic} />
|
|
23
|
+
</Tooltip>
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export default SaveTopic;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Icon } from '@lobehub/ui';
|
|
2
|
+
import { useTheme } from 'antd-style';
|
|
3
|
+
import { ArrowBigUp, CornerDownLeft } from 'lucide-react';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Flexbox } from 'react-layout-kit';
|
|
7
|
+
|
|
8
|
+
import SaveTopic from './SaveTopic';
|
|
9
|
+
|
|
10
|
+
const Footer = memo(() => {
|
|
11
|
+
const theme = useTheme();
|
|
12
|
+
const { t } = useTranslation('common');
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
<Flexbox
|
|
17
|
+
gap={4}
|
|
18
|
+
horizontal
|
|
19
|
+
style={{ color: theme.colorTextDescription, fontSize: 12, marginRight: 12 }}
|
|
20
|
+
>
|
|
21
|
+
<Icon icon={CornerDownLeft} />
|
|
22
|
+
<span>{t('send')}</span>
|
|
23
|
+
<span>/</span>
|
|
24
|
+
<Flexbox horizontal>
|
|
25
|
+
<Icon icon={ArrowBigUp} />
|
|
26
|
+
<Icon icon={CornerDownLeft} />
|
|
27
|
+
</Flexbox>
|
|
28
|
+
<span>{t('warp')}</span>
|
|
29
|
+
</Flexbox>
|
|
30
|
+
<SaveTopic />
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export default Footer;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ReactNode, memo } from 'react';
|
|
2
|
+
|
|
3
|
+
interface ChatInputMobileLayoutProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
expand?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const ChatInputMobileLayout = memo<ChatInputMobileLayoutProps>(({ children }) => {
|
|
9
|
+
return <div>{children}</div>;
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export default ChatInputMobileLayout;
|
|
@@ -1,64 +1,46 @@
|
|
|
1
|
-
import { ChatInputArea
|
|
1
|
+
import { ChatInputArea } from '@lobehub/ui';
|
|
2
|
+
import { useResponsive } from 'antd-style';
|
|
2
3
|
import { memo, useState } from 'react';
|
|
3
4
|
import { useTranslation } from 'react-i18next';
|
|
4
5
|
|
|
5
|
-
import { CHAT_TEXTAREA_HEIGHT
|
|
6
|
-
import { useGlobalStore } from '@/store/global';
|
|
6
|
+
import { CHAT_TEXTAREA_HEIGHT } from '@/const/layoutTokens';
|
|
7
7
|
import { useSessionStore } from '@/store/session';
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
import ActionsRight from './ActionRight';
|
|
9
|
+
import ActionLeft from './ActionBar/ActionLeft';
|
|
10
|
+
import ActionsRight from './ActionBar/ActionRight';
|
|
11
|
+
import Token from './ActionBar/Token';
|
|
12
|
+
import Desktop from './Desktop';
|
|
11
13
|
import Footer from './Footer';
|
|
12
|
-
import
|
|
14
|
+
import Mobile from './Mobile';
|
|
13
15
|
|
|
14
16
|
const ChatInput = () => {
|
|
15
17
|
const { t } = useTranslation('common');
|
|
16
18
|
const [expand, setExpand] = useState<boolean>(false);
|
|
17
19
|
const [message, setMessage] = useState('');
|
|
20
|
+
const { mobile } = useResponsive();
|
|
18
21
|
|
|
19
|
-
const [
|
|
20
|
-
s.
|
|
21
|
-
s.
|
|
22
|
+
const [isLoading, sendMessage, stopGenerateMessage] = useSessionStore((s) => [
|
|
23
|
+
!!s.chatLoadingId,
|
|
24
|
+
s.sendMessage,
|
|
25
|
+
s.stopGenerateMessage,
|
|
22
26
|
]);
|
|
23
|
-
const [isLoading, hasTopic, sendMessage, saveToTopic, stopGenerateMessage] = useSessionStore(
|
|
24
|
-
(s) => [
|
|
25
|
-
!!s.chatLoadingId,
|
|
26
|
-
!!s.activeTopicId,
|
|
27
|
-
s.sendMessage,
|
|
28
|
-
s.saveToTopic,
|
|
29
|
-
s.stopGenerateMessage,
|
|
30
|
-
],
|
|
31
|
-
);
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
<DraggablePanel
|
|
35
|
-
expandable={false}
|
|
36
|
-
fullscreen={expand}
|
|
37
|
-
headerHeight={HEADER_HEIGHT}
|
|
38
|
-
minHeight={CHAT_TEXTAREA_HEIGHT}
|
|
39
|
-
onSizeChange={(_, size) => {
|
|
40
|
-
if (!size) return;
|
|
28
|
+
const Render = mobile ? Mobile : Desktop;
|
|
41
29
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
});
|
|
45
|
-
}}
|
|
46
|
-
placement="bottom"
|
|
47
|
-
size={{ height: inputHeight, width: '100%' }}
|
|
48
|
-
style={{ zIndex: 10 }}
|
|
49
|
-
>
|
|
30
|
+
return (
|
|
31
|
+
<Render expand={expand}>
|
|
50
32
|
<ChatInputArea
|
|
51
33
|
actions={
|
|
52
34
|
<>
|
|
53
|
-
<
|
|
35
|
+
<ActionLeft />
|
|
54
36
|
<Token input={message} />
|
|
55
37
|
</>
|
|
56
38
|
}
|
|
57
39
|
actionsRight={<ActionsRight />}
|
|
58
40
|
expand={expand}
|
|
59
|
-
footer={<Footer
|
|
41
|
+
footer={<Footer />}
|
|
60
42
|
loading={isLoading}
|
|
61
|
-
minHeight={CHAT_TEXTAREA_HEIGHT}
|
|
43
|
+
minHeight={mobile ? 0 : CHAT_TEXTAREA_HEIGHT}
|
|
62
44
|
onExpandChange={setExpand}
|
|
63
45
|
onInputChange={setMessage}
|
|
64
46
|
onSend={sendMessage}
|
|
@@ -70,7 +52,7 @@ const ChatInput = () => {
|
|
|
70
52
|
}}
|
|
71
53
|
value={message}
|
|
72
54
|
/>
|
|
73
|
-
</
|
|
55
|
+
</Render>
|
|
74
56
|
);
|
|
75
57
|
};
|
|
76
58
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActionIcon, Logo
|
|
1
|
+
import { ActionIcon, Logo } from '@lobehub/ui';
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
3
|
import { MessageSquarePlus } from 'lucide-react';
|
|
4
4
|
import Link from 'next/link';
|
|
@@ -8,6 +8,8 @@ import { Flexbox } from 'react-layout-kit';
|
|
|
8
8
|
|
|
9
9
|
import { useSessionStore } from '@/store/session';
|
|
10
10
|
|
|
11
|
+
import SessionSearchBar from '../../SessionSearchBar';
|
|
12
|
+
|
|
11
13
|
export const useStyles = createStyles(({ css, token }) => ({
|
|
12
14
|
logo: css`
|
|
13
15
|
fill: ${token.colorText};
|
|
@@ -21,7 +23,7 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|
|
21
23
|
const Header = memo(() => {
|
|
22
24
|
const { styles } = useStyles();
|
|
23
25
|
const { t } = useTranslation('common');
|
|
24
|
-
const [
|
|
26
|
+
const [createSession] = useSessionStore((s) => [s.createSession]);
|
|
25
27
|
|
|
26
28
|
return (
|
|
27
29
|
<Flexbox className={styles.top} gap={16} padding={16}>
|
|
@@ -31,22 +33,13 @@ const Header = memo(() => {
|
|
|
31
33
|
</Link>
|
|
32
34
|
<ActionIcon
|
|
33
35
|
icon={MessageSquarePlus}
|
|
34
|
-
onClick={createSession}
|
|
36
|
+
onClick={() => createSession()}
|
|
35
37
|
size={{ fontSize: 24 }}
|
|
36
38
|
style={{ flex: 'none' }}
|
|
37
39
|
title={t('newAgent')}
|
|
38
40
|
/>
|
|
39
41
|
</Flexbox>
|
|
40
|
-
<
|
|
41
|
-
allowClear
|
|
42
|
-
enableShortKey
|
|
43
|
-
onChange={(e) => useSessionStore.setState({ searchKeywords: e.target.value })}
|
|
44
|
-
placeholder={t('searchAgentPlaceholder')}
|
|
45
|
-
shortKey={'k'}
|
|
46
|
-
spotlight
|
|
47
|
-
type={'ghost'}
|
|
48
|
-
value={keywords}
|
|
49
|
-
/>
|
|
42
|
+
<SessionSearchBar />
|
|
50
43
|
</Flexbox>
|
|
51
44
|
);
|
|
52
45
|
});
|
|
@@ -26,7 +26,7 @@ const Header = memo(() => {
|
|
|
26
26
|
left={<AvatarWithUpload size={28} style={{ marginLeft: 8 }} />}
|
|
27
27
|
right={
|
|
28
28
|
<>
|
|
29
|
-
<ActionIcon icon={MessageSquarePlus} onClick={createSession} />
|
|
29
|
+
<ActionIcon icon={MessageSquarePlus} onClick={() => createSession()} />
|
|
30
30
|
<ActionIcon
|
|
31
31
|
icon={Settings2}
|
|
32
32
|
onClick={() => {
|
|
@@ -12,7 +12,7 @@ const AddButton = memo<ButtonProps>((props) => {
|
|
|
12
12
|
const createSession = useSessionStore((s) => s.createSession);
|
|
13
13
|
return (
|
|
14
14
|
<Flexbox style={{ margin: '12px 16px' }}>
|
|
15
|
-
<Button block icon={<Icon icon={Plus} />} onClick={createSession} {...props}>
|
|
15
|
+
<Button block icon={<Icon icon={Plus} />} onClick={() => createSession()} {...props}>
|
|
16
16
|
{t('newAgent')}
|
|
17
17
|
</Button>
|
|
18
18
|
</Flexbox>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SiOpenai } from '@icons-pack/react-simple-icons';
|
|
2
2
|
import { Avatar, List, Tag } from '@lobehub/ui';
|
|
3
3
|
import { useHover } from 'ahooks';
|
|
4
|
-
import { createStyles } from 'antd-style';
|
|
4
|
+
import { createStyles, useResponsive } from 'antd-style';
|
|
5
5
|
import { memo, useMemo, useRef, useState } from 'react';
|
|
6
6
|
import { Flexbox } from 'react-layout-kit';
|
|
7
7
|
import { shallow } from 'zustand/shallow';
|
|
@@ -34,7 +34,7 @@ const SessionItem = memo<SessionItemProps>(({ id }) => {
|
|
|
34
34
|
const [open, setOpen] = useState(false);
|
|
35
35
|
const ref = useRef(null);
|
|
36
36
|
const isHovering = useHover(ref);
|
|
37
|
-
|
|
37
|
+
const { mobile } = useResponsive();
|
|
38
38
|
const { styles } = useStyles();
|
|
39
39
|
const [defaultModel] = useGlobalStore((s) => [globalSelectors.defaultAgentConfig(s).model]);
|
|
40
40
|
|
|
@@ -98,7 +98,8 @@ const SessionItem = memo<SessionItemProps>(({ id }) => {
|
|
|
98
98
|
return (
|
|
99
99
|
<Item
|
|
100
100
|
actions={actions}
|
|
101
|
-
active
|
|
101
|
+
// needn't active state in mobile
|
|
102
|
+
active={mobile ? false : active}
|
|
102
103
|
addon={addon}
|
|
103
104
|
avatar={avatarRender}
|
|
104
105
|
className={styles.container}
|