@lobehub/chat 1.97.7 → 1.97.8
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/CHANGELOG.md +17 -0
- package/changelog/v1.json +5 -0
- package/package.json +2 -2
- package/src/app/[variants]/(main)/discover/(detail)/assistant/[...slugs]/features/Details/Nav.tsx +4 -3
- package/src/app/[variants]/(main)/discover/(detail)/features/MakedownRender.tsx +3 -0
- package/src/app/[variants]/(main)/discover/(detail)/features/Toc/useToc.tsx +9 -2
- package/src/app/[variants]/(main)/discover/(detail)/model/[...slugs]/features/Details/Nav.tsx +4 -2
- package/src/app/[variants]/(main)/discover/(detail)/provider/[...slugs]/features/Details/Nav.tsx +4 -2
- package/src/app/[variants]/(main)/discover/(list)/features/SortButton/index.tsx +1 -0
- package/src/app/[variants]/(main)/files/(content)/@modal/(.)[id]/page.tsx +2 -0
- package/src/app/[variants]/(main)/files/[id]/page.tsx +2 -0
- package/src/app/[variants]/(main)/repos/[id]/Client.tsx +29 -0
- package/src/app/[variants]/(main)/repos/[id]/features/Menu/Head/index.tsx +12 -4
- package/src/app/[variants]/(main)/repos/[id]/features/Menu/Menu/index.tsx +4 -1
- package/src/app/[variants]/(main)/repos/[id]/features/Menu/index.tsx +8 -8
- package/src/app/[variants]/(main)/repos/[id]/layout.tsx +2 -0
- package/src/app/[variants]/(main)/repos/[id]/page.tsx +2 -22
- package/src/app/[variants]/(main)/repos/loading.tsx +3 -0
- package/src/app/[variants]/(main)/settings/agent/AgentMenu/Menu.tsx +17 -0
- package/src/app/[variants]/(main)/settings/agent/AgentMenu/index.tsx +12 -8
- package/src/app/[variants]/(main)/settings/agent/page.tsx +15 -1
- package/src/app/[variants]/(main)/settings/provider/(detail)/[id]/ClientMode.tsx +16 -4
- package/src/app/[variants]/(main)/settings/provider/(detail)/[id]/page.tsx +2 -30
- package/src/app/[variants]/(main)/settings/provider/layout.tsx +0 -2
- package/src/components/NProgress/index.tsx +11 -7
- package/src/features/ChatInput/ActionBar/STT/common.tsx +1 -0
- package/src/features/KnowledgeBaseModal/CreateNew/CreateForm.tsx +5 -1
- package/src/features/MCPPluginDetail/Schema/Prompts.tsx +4 -2
- package/src/features/MCPPluginDetail/Schema/Tools.tsx +4 -2
- package/src/features/MCPPluginDetail/Score/GithubBadge/index.tsx +2 -0
- package/src/features/ModelSelect/index.tsx +3 -1
- package/src/features/ModelSwitchPanel/index.tsx +1 -0
- package/src/services/aiProvider/type.ts +2 -1
- package/src/store/knowledgeBase/slices/crud/action.ts +21 -4
- package/src/store/knowledgeBase/slices/crud/initialState.ts +4 -0
- package/src/store/knowledgeBase/slices/crud/selectors.ts +7 -0
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,23 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.97.8](https://github.com/lobehub/lobe-chat/compare/v1.97.7...v1.97.8)
|
6
|
+
|
7
|
+
<sup>Released on **2025-07-10**</sup>
|
8
|
+
|
9
|
+
<br/>
|
10
|
+
|
11
|
+
<details>
|
12
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
13
|
+
|
14
|
+
</details>
|
15
|
+
|
16
|
+
<div align="right">
|
17
|
+
|
18
|
+
[](#readme-top)
|
19
|
+
|
20
|
+
</div>
|
21
|
+
|
5
22
|
### [Version 1.97.7](https://github.com/lobehub/lobe-chat/compare/v1.97.6...v1.97.7)
|
6
23
|
|
7
24
|
<sup>Released on **2025-07-10**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.97.
|
3
|
+
"version": "1.97.8",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -171,7 +171,7 @@
|
|
171
171
|
"@xterm/xterm": "^5.5.0",
|
172
172
|
"ahooks": "^3.8.5",
|
173
173
|
"ai": "^3.4.33",
|
174
|
-
"antd": "5.26.
|
174
|
+
"antd": "^5.26.4",
|
175
175
|
"antd-style": "^3.7.1",
|
176
176
|
"brotli-wasm": "^3.0.1",
|
177
177
|
"chroma-js": "^3.1.2",
|
package/src/app/[variants]/(main)/discover/(detail)/assistant/[...slugs]/features/Details/Nav.tsx
CHANGED
@@ -28,12 +28,13 @@ const useStyles = createStyles(({ css, token }) => {
|
|
28
28
|
`,
|
29
29
|
};
|
30
30
|
});
|
31
|
-
|
32
|
-
const Nav = memo<{
|
31
|
+
interface NavProps {
|
33
32
|
activeTab?: AssistantNavKey;
|
34
33
|
mobile?: boolean;
|
35
34
|
setActiveTab?: (tab: AssistantNavKey) => void;
|
36
|
-
}
|
35
|
+
}
|
36
|
+
|
37
|
+
const Nav = memo<NavProps>(({ mobile, setActiveTab, activeTab = AssistantNavKey.Overview }) => {
|
37
38
|
const { t } = useTranslation('discover');
|
38
39
|
const { pluginCount, knowledgeCount, identifier } = useDetailContext();
|
39
40
|
const { styles } = useStyles();
|
@@ -13,6 +13,7 @@ const MarkdownRender = memo<{ children?: string }>(({ children }) => {
|
|
13
13
|
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
14
14
|
</Center>
|
15
15
|
);
|
16
|
+
|
16
17
|
return (
|
17
18
|
<Markdown
|
18
19
|
allowHtml
|
@@ -29,6 +30,8 @@ const MarkdownRender = memo<{ children?: string }>(({ children }) => {
|
|
29
30
|
h5: H5,
|
30
31
|
img: ({ src, ...rest }: { src: string }) => {
|
31
32
|
if (src.includes('glama.ai')) return;
|
33
|
+
|
34
|
+
// eslint-disable-next-line @next/next/no-img-element
|
32
35
|
if (src && src.startsWith('http')) return <img src={src} {...rest} />;
|
33
36
|
return;
|
34
37
|
},
|
@@ -4,12 +4,19 @@ import { AnchorProps } from 'antd';
|
|
4
4
|
import { unionBy } from 'lodash-es';
|
5
5
|
import { FC, PropsWithChildren, createContext, useContext, useState } from 'react';
|
6
6
|
|
7
|
-
|
7
|
+
interface TocState {
|
8
8
|
isLoading: boolean;
|
9
9
|
setFinished: () => void;
|
10
10
|
setToc: (data: any) => void;
|
11
11
|
toc?: AnchorProps['items'];
|
12
|
-
}
|
12
|
+
}
|
13
|
+
|
14
|
+
const TocContext = createContext<TocState>({
|
15
|
+
isLoading: true,
|
16
|
+
setFinished: () => {},
|
17
|
+
setToc: () => {},
|
18
|
+
toc: [],
|
19
|
+
});
|
13
20
|
|
14
21
|
export interface TOCItem {
|
15
22
|
href: string;
|
package/src/app/[variants]/(main)/discover/(detail)/model/[...slugs]/features/Details/Nav.tsx
CHANGED
@@ -26,11 +26,13 @@ const useStyles = createStyles(({ css, token }) => {
|
|
26
26
|
};
|
27
27
|
});
|
28
28
|
|
29
|
-
|
29
|
+
interface NavProps {
|
30
30
|
activeTab?: ModelNavKey;
|
31
31
|
mobile?: boolean;
|
32
32
|
setActiveTab?: (tab: ModelNavKey) => void;
|
33
|
-
}
|
33
|
+
}
|
34
|
+
|
35
|
+
const Nav = memo<NavProps>(({ mobile, setActiveTab, activeTab = ModelNavKey.Overview }) => {
|
34
36
|
const { t } = useTranslation('discover');
|
35
37
|
const { styles } = useStyles();
|
36
38
|
|
package/src/app/[variants]/(main)/discover/(detail)/provider/[...slugs]/features/Details/Nav.tsx
CHANGED
@@ -29,11 +29,13 @@ const useStyles = createStyles(({ css, token }) => {
|
|
29
29
|
};
|
30
30
|
});
|
31
31
|
|
32
|
-
|
32
|
+
interface NavProps {
|
33
33
|
activeTab?: ProviderNavKey;
|
34
34
|
mobile?: boolean;
|
35
35
|
setActiveTab?: (tab: ProviderNavKey) => void;
|
36
|
-
}
|
36
|
+
}
|
37
|
+
|
38
|
+
const Nav = memo<NavProps>(({ mobile, setActiveTab, activeTab = ProviderNavKey.Overview }) => {
|
37
39
|
const { t } = useTranslation('discover');
|
38
40
|
const { identifier } = useDetailContext();
|
39
41
|
const { styles } = useStyles();
|
@@ -0,0 +1,29 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { memo } from 'react';
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
5
|
+
|
6
|
+
import FileManager from '@/features/FileManager';
|
7
|
+
import FilePanel from '@/features/FileSidePanel';
|
8
|
+
import { knowledgeBaseSelectors, useKnowledgeBaseStore } from '@/store/knowledgeBase';
|
9
|
+
|
10
|
+
import Menu from './features/Menu';
|
11
|
+
import { useKnowledgeBaseItem } from './hooks/useKnowledgeItem';
|
12
|
+
|
13
|
+
const RepoClientPage = memo<{ id: string }>(({ id }) => {
|
14
|
+
useKnowledgeBaseItem(id);
|
15
|
+
const name = useKnowledgeBaseStore(knowledgeBaseSelectors.getKnowledgeBaseNameById(id));
|
16
|
+
|
17
|
+
return (
|
18
|
+
<>
|
19
|
+
<FilePanel>
|
20
|
+
<Menu id={id} />
|
21
|
+
</FilePanel>
|
22
|
+
<Flexbox flex={1} style={{ overflow: 'hidden', position: 'relative' }}>
|
23
|
+
<FileManager knowledgeBaseId={id} title={name} />
|
24
|
+
</Flexbox>
|
25
|
+
</>
|
26
|
+
);
|
27
|
+
});
|
28
|
+
|
29
|
+
export default RepoClientPage;
|
@@ -1,13 +1,17 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
3
|
import { Text } from '@lobehub/ui';
|
4
|
+
import { Skeleton } from 'antd';
|
4
5
|
import { memo } from 'react';
|
5
6
|
import { Center, Flexbox } from 'react-layout-kit';
|
6
7
|
|
7
8
|
import GoBack from '@/components/GoBack';
|
8
9
|
import RepoIcon from '@/components/RepoIcon';
|
10
|
+
import { knowledgeBaseSelectors, useKnowledgeBaseStore } from '@/store/knowledgeBase';
|
11
|
+
|
12
|
+
const Head = memo<{ id: string }>(({ id }) => {
|
13
|
+
const name = useKnowledgeBaseStore(knowledgeBaseSelectors.getKnowledgeBaseNameById(id));
|
9
14
|
|
10
|
-
const Head = memo<{ name?: string }>(({ name }) => {
|
11
15
|
return (
|
12
16
|
<Flexbox gap={8}>
|
13
17
|
<GoBack href={'/files'} />
|
@@ -16,9 +20,13 @@ const Head = memo<{ name?: string }>(({ name }) => {
|
|
16
20
|
<RepoIcon />
|
17
21
|
</Center>
|
18
22
|
|
19
|
-
|
20
|
-
{
|
21
|
-
|
23
|
+
{!name ? (
|
24
|
+
<Skeleton active paragraph={false} title={{ style: { marginBottom: 0 }, width: 80 }} />
|
25
|
+
) : (
|
26
|
+
<Text ellipsis strong style={{ fontSize: 16 }}>
|
27
|
+
{name}
|
28
|
+
</Text>
|
29
|
+
)}
|
22
30
|
</Flexbox>
|
23
31
|
</Flexbox>
|
24
32
|
);
|
@@ -10,12 +10,15 @@ import { Flexbox } from 'react-layout-kit';
|
|
10
10
|
|
11
11
|
import Menu from '@/components/Menu';
|
12
12
|
import type { MenuProps } from '@/components/Menu';
|
13
|
+
import { useKnowledgeBaseStore } from '@/store/knowledgeBase';
|
13
14
|
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
|
14
15
|
|
15
|
-
const FileMenu = memo
|
16
|
+
const FileMenu = memo(() => {
|
16
17
|
const { t } = useTranslation('knowledgeBase');
|
17
18
|
const pathname = usePathname();
|
18
19
|
const { enableRAGEval } = useServerConfigStore(featureFlagsSelectors);
|
20
|
+
const id = useKnowledgeBaseStore((s) => s.activeKnowledgeBaseId);
|
21
|
+
|
19
22
|
const [activeKey, setActiveKey] = useState(
|
20
23
|
pathname.startsWith(`/repos/${id}/evals`) ? 'eval' : 'files',
|
21
24
|
);
|
@@ -4,14 +4,14 @@ import { Flexbox } from 'react-layout-kit';
|
|
4
4
|
import Head from './Head';
|
5
5
|
import Menu from './Menu';
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
)
|
7
|
+
const ComposeMenu = memo<{ id: string }>(({ id }) => {
|
8
|
+
return (
|
9
|
+
<Flexbox gap={16} height={'100%'} paddingInline={12} style={{ paddingTop: 12 }}>
|
10
|
+
<Head id={id} />
|
11
|
+
<Menu />
|
12
|
+
</Flexbox>
|
13
|
+
);
|
14
|
+
});
|
15
15
|
|
16
16
|
ComposeMenu.displayName = 'ComposeMenu';
|
17
17
|
|
@@ -1,29 +1,9 @@
|
|
1
|
-
import { redirect } from 'next/navigation';
|
2
|
-
import { Flexbox } from 'react-layout-kit';
|
3
|
-
|
4
|
-
import { KnowledgeBaseModel } from '@/database/models/knowledgeBase';
|
5
|
-
import { getServerDB } from '@/database/server';
|
6
|
-
import FileManager from '@/features/FileManager';
|
7
|
-
import FilePanel from '@/features/FileSidePanel';
|
8
1
|
import { PagePropsWithId } from '@/types/next';
|
9
2
|
|
10
|
-
import
|
3
|
+
import Client from './Client';
|
11
4
|
|
12
5
|
export default async (props: PagePropsWithId) => {
|
13
6
|
const params = await props.params;
|
14
7
|
|
15
|
-
|
16
|
-
const item = await KnowledgeBaseModel.findById(serverDB, params.id);
|
17
|
-
if (!item) return redirect('/repos');
|
18
|
-
|
19
|
-
return (
|
20
|
-
<>
|
21
|
-
<FilePanel>
|
22
|
-
<Menu id={params.id} name={item.name} />
|
23
|
-
</FilePanel>
|
24
|
-
<Flexbox flex={1} style={{ overflow: 'hidden', position: 'relative' }}>
|
25
|
-
<FileManager knowledgeBaseId={params.id} title={item.name} />
|
26
|
-
</Flexbox>
|
27
|
-
</>
|
28
|
-
);
|
8
|
+
return <Client id={params.id} />;
|
29
9
|
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { useQueryState } from 'nuqs';
|
4
|
+
import { memo } from 'react';
|
5
|
+
|
6
|
+
import { AgentCategory } from '@/features/AgentSetting';
|
7
|
+
import { ChatSettingsTabs } from '@/store/global/initialState';
|
8
|
+
|
9
|
+
const Menu = memo(() => {
|
10
|
+
const [tab, setTab] = useQueryState('tab', {
|
11
|
+
defaultValue: ChatSettingsTabs.Prompt,
|
12
|
+
});
|
13
|
+
|
14
|
+
return <AgentCategory setTab={setTab} tab={tab} />;
|
15
|
+
});
|
16
|
+
|
17
|
+
export default Menu;
|
@@ -1,14 +1,13 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
3
|
import { Alert } from '@lobehub/ui';
|
4
|
+
import { Skeleton } from 'antd';
|
4
5
|
import { useTheme } from 'antd-style';
|
5
|
-
import {
|
6
|
-
import { memo } from 'react';
|
6
|
+
import { Suspense, memo } from 'react';
|
7
7
|
import { useTranslation } from 'react-i18next';
|
8
8
|
import { Flexbox } from 'react-layout-kit';
|
9
9
|
|
10
|
-
import
|
11
|
-
import { ChatSettingsTabs } from '@/store/global/initialState';
|
10
|
+
import Menu from './Menu';
|
12
11
|
|
13
12
|
interface ProviderMenuProps {
|
14
13
|
mobile?: boolean;
|
@@ -16,9 +15,6 @@ interface ProviderMenuProps {
|
|
16
15
|
const ProviderMenu = memo(({ mobile }: ProviderMenuProps) => {
|
17
16
|
const theme = useTheme();
|
18
17
|
const { t } = useTranslation('setting');
|
19
|
-
const [tab, setTab] = useQueryState('tab', {
|
20
|
-
defaultValue: ChatSettingsTabs.Prompt,
|
21
|
-
});
|
22
18
|
|
23
19
|
const width = mobile ? undefined : 260;
|
24
20
|
return (
|
@@ -41,7 +37,15 @@ const ProviderMenu = memo(({ mobile }: ProviderMenuProps) => {
|
|
41
37
|
}}
|
42
38
|
variant={'filled'}
|
43
39
|
/>
|
44
|
-
<
|
40
|
+
<Suspense
|
41
|
+
fallback={
|
42
|
+
<Flexbox gap={4} paddingBlock={8} paddingInline={8}>
|
43
|
+
<Skeleton active paragraph={{ rows: 4 }} title={false} />
|
44
|
+
</Flexbox>
|
45
|
+
}
|
46
|
+
>
|
47
|
+
<Menu />
|
48
|
+
</Suspense>
|
45
49
|
</Flexbox>
|
46
50
|
);
|
47
51
|
});
|
@@ -1,8 +1,13 @@
|
|
1
|
+
import { Skeleton } from 'antd';
|
2
|
+
import { Suspense } from 'react';
|
3
|
+
|
1
4
|
import { metadataModule } from '@/server/metadata';
|
2
5
|
import { translation } from '@/server/translation';
|
3
6
|
import { DynamicLayoutProps } from '@/types/next';
|
4
7
|
import { RouteVariants } from '@/utils/server/routeVariants';
|
5
8
|
|
9
|
+
import Page from './index';
|
10
|
+
|
6
11
|
export const generateMetadata = async (props: DynamicLayoutProps) => {
|
7
12
|
const locale = await RouteVariants.getLocale(props);
|
8
13
|
const { t } = await translation('setting', locale);
|
@@ -12,4 +17,13 @@ export const generateMetadata = async (props: DynamicLayoutProps) => {
|
|
12
17
|
url: '/settings/agent',
|
13
18
|
});
|
14
19
|
};
|
15
|
-
|
20
|
+
|
21
|
+
export default () => {
|
22
|
+
return (
|
23
|
+
<Suspense fallback={<Skeleton active paragraph={{ rows: 5 }} title={false} />}>
|
24
|
+
<Page />
|
25
|
+
</Suspense>
|
26
|
+
);
|
27
|
+
};
|
28
|
+
|
29
|
+
export const dynamic = 'force-static';
|
@@ -1,22 +1,34 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
|
-
import {
|
3
|
+
import { useRouter } from 'next/navigation';
|
4
|
+
import { memo, useEffect } from 'react';
|
4
5
|
import { Flexbox } from 'react-layout-kit';
|
5
|
-
import useSWR from 'swr';
|
6
6
|
|
7
|
+
import Loading from '@/components/Loading/BrandTextLoading';
|
8
|
+
import { useClientDataSWR } from '@/libs/swr';
|
7
9
|
import { aiProviderService } from '@/services/aiProvider';
|
8
10
|
|
9
11
|
import ModelList from '../../features/ModelList';
|
10
12
|
import ProviderConfig from '../../features/ProviderConfig';
|
11
13
|
|
12
14
|
const ClientMode = memo<{ id: string }>(({ id }) => {
|
13
|
-
const { data, isLoading } =
|
15
|
+
const { data, isLoading } = useClientDataSWR('get-client-provider', () =>
|
14
16
|
aiProviderService.getAiProviderById(id),
|
15
17
|
);
|
16
18
|
|
19
|
+
const router = useRouter();
|
20
|
+
|
21
|
+
useEffect(() => {
|
22
|
+
if (!isLoading && !data?.id) {
|
23
|
+
router.push('/settings/provider');
|
24
|
+
}
|
25
|
+
}, [isLoading, data]);
|
26
|
+
|
27
|
+
if (isLoading || !data || !data.id) return <Loading />;
|
28
|
+
|
17
29
|
return (
|
18
30
|
<Flexbox gap={24} paddingBlock={8}>
|
19
|
-
|
31
|
+
<ProviderConfig {...data} id={id} name={data.name || ''} />
|
20
32
|
<ModelList id={id} />
|
21
33
|
</Flexbox>
|
22
34
|
);
|
@@ -1,14 +1,5 @@
|
|
1
|
-
import { redirect } from 'next/navigation';
|
2
|
-
|
3
1
|
import { DEFAULT_MODEL_PROVIDER_LIST } from '@/config/modelProviders';
|
4
|
-
import { isDesktop, isServerMode } from '@/const/version';
|
5
|
-
import { AiInfraRepos } from '@/database/repositories/aiInfra';
|
6
|
-
import { serverDB } from '@/database/server';
|
7
|
-
import { getServerGlobalConfig } from '@/server/globalConfig';
|
8
|
-
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
9
2
|
import { PagePropsWithId } from '@/types/next';
|
10
|
-
import { ProviderConfig } from '@/types/user/settings';
|
11
|
-
import { getUserAuth } from '@/utils/server/auth';
|
12
3
|
|
13
4
|
import ClientMode from './ClientMode';
|
14
5
|
import ProviderDetail from './index';
|
@@ -20,28 +11,9 @@ const Page = async (props: PagePropsWithId) => {
|
|
20
11
|
// if builtin provider
|
21
12
|
if (!!builtinProviderCard) return <ProviderDetail source={'builtin'} {...builtinProviderCard} />;
|
22
13
|
|
23
|
-
// if user custom provider
|
24
|
-
if (!isDesktop && isServerMode) {
|
25
|
-
const { userId } = await getUserAuth();
|
26
|
-
|
27
|
-
const { aiProvider } = await getServerGlobalConfig();
|
28
|
-
const aiInfraRepos = new AiInfraRepos(
|
29
|
-
serverDB,
|
30
|
-
userId!,
|
31
|
-
aiProvider as Record<string, ProviderConfig>,
|
32
|
-
);
|
33
|
-
|
34
|
-
const userCard = await aiInfraRepos.getAiProviderDetail(
|
35
|
-
params.id,
|
36
|
-
KeyVaultsGateKeeper.getUserKeyVaults,
|
37
|
-
);
|
38
|
-
|
39
|
-
if (!userCard) return redirect('/settings/provider');
|
40
|
-
|
41
|
-
return <ProviderDetail {...userCard} />;
|
42
|
-
}
|
43
|
-
|
44
14
|
return <ClientMode id={params.id} />;
|
45
15
|
};
|
46
16
|
|
47
17
|
export default Page;
|
18
|
+
|
19
|
+
export const dynamic = 'force-static';
|
@@ -4,16 +4,20 @@ import { useTheme } from 'antd-style';
|
|
4
4
|
import NextTopLoader from 'nextjs-toploader';
|
5
5
|
import { memo } from 'react';
|
6
6
|
|
7
|
+
import { isDesktop } from '@/const/version';
|
8
|
+
|
7
9
|
const NProgress = memo(() => {
|
8
10
|
const theme = useTheme();
|
9
11
|
return (
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
!isDesktop && (
|
13
|
+
<NextTopLoader
|
14
|
+
color={theme.colorText}
|
15
|
+
height={2}
|
16
|
+
shadow={false}
|
17
|
+
showSpinner={false}
|
18
|
+
zIndex={1000}
|
19
|
+
/>
|
20
|
+
)
|
17
21
|
);
|
18
22
|
});
|
19
23
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { Button, Form, Input, TextArea } from '@lobehub/ui';
|
2
|
+
import { useRouter } from 'next/navigation';
|
2
3
|
import { memo, useState } from 'react';
|
3
4
|
import { useTranslation } from 'react-i18next';
|
4
5
|
|
@@ -13,14 +14,17 @@ const CreateForm = memo<CreateFormProps>(({ onClose }) => {
|
|
13
14
|
const { t } = useTranslation('knowledgeBase');
|
14
15
|
const [loading, setLoading] = useState(false);
|
15
16
|
const createNewKnowledgeBase = useKnowledgeBaseStore((s) => s.createNewKnowledgeBase);
|
17
|
+
const router = useRouter();
|
16
18
|
|
17
19
|
const onFinish = async (values: CreateKnowledgeBaseParams) => {
|
18
20
|
setLoading(true);
|
19
21
|
|
20
22
|
try {
|
21
|
-
await createNewKnowledgeBase(values);
|
23
|
+
const id = await createNewKnowledgeBase(values);
|
22
24
|
setLoading(false);
|
23
25
|
onClose?.();
|
26
|
+
|
27
|
+
router.push(`/repos/${id}`);
|
24
28
|
} catch (e) {
|
25
29
|
console.error(e);
|
26
30
|
setLoading(false);
|
@@ -14,11 +14,13 @@ import { useDetailContext } from '../DetailProvider';
|
|
14
14
|
import { useStyles } from './style';
|
15
15
|
import { ModeType } from './types';
|
16
16
|
|
17
|
-
|
17
|
+
interface PromptsProps {
|
18
18
|
activeKey?: string[];
|
19
19
|
mode?: ModeType;
|
20
20
|
setActiveKey?: (key: string[]) => void;
|
21
|
-
}
|
21
|
+
}
|
22
|
+
|
23
|
+
const Prompts = memo<PromptsProps>(({ mode, activeKey = [], setActiveKey }) => {
|
22
24
|
const { t } = useTranslation('discover');
|
23
25
|
const { prompts } = useDetailContext();
|
24
26
|
const { styles, theme } = useStyles();
|
@@ -14,11 +14,13 @@ import { useDetailContext } from '../DetailProvider';
|
|
14
14
|
import { useStyles } from './style';
|
15
15
|
import { ModeType } from './types';
|
16
16
|
|
17
|
-
|
17
|
+
interface ToolsProps {
|
18
18
|
activeKey?: string[];
|
19
19
|
mode?: ModeType;
|
20
20
|
setActiveKey?: (key: string[]) => void;
|
21
|
-
}
|
21
|
+
}
|
22
|
+
|
23
|
+
const Tools = memo<ToolsProps>(({ mode, activeKey = [], setActiveKey }) => {
|
22
24
|
const { t } = useTranslation('discover');
|
23
25
|
const { tools } = useDetailContext();
|
24
26
|
const { styles, theme } = useStyles();
|
@@ -59,6 +59,7 @@ const GithubBadge = memo(() => {
|
|
59
59
|
<Snippet language={'md'} style={{ fontSize: 12 }} variant={'outlined'}>
|
60
60
|
{badgeLite}
|
61
61
|
</Snippet>
|
62
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
62
63
|
<img
|
63
64
|
alt="MCP Badge"
|
64
65
|
height={selectedStyle === 'for-the-badge' ? 28 : 20}
|
@@ -74,6 +75,7 @@ const GithubBadge = memo(() => {
|
|
74
75
|
<Snippet language={'md'} style={{ fontSize: 12 }} variant={'outlined'}>
|
75
76
|
{badge}
|
76
77
|
</Snippet>
|
78
|
+
{/* eslint-disable-next-line @next/next/no-img-element */}
|
77
79
|
<img alt="MCP Badge" src={styledBadgeFullUrl} />
|
78
80
|
</>
|
79
81
|
);
|
@@ -69,13 +69,15 @@ const ModelSelect = memo<ModelSelectProps>(({ value, onChange, showAbility = tru
|
|
69
69
|
return (
|
70
70
|
<Select
|
71
71
|
className={styles.select}
|
72
|
+
classNames={{
|
73
|
+
popup: { root: styles.popup },
|
74
|
+
}}
|
72
75
|
defaultValue={`${value?.provider}/${value?.model}`}
|
73
76
|
onChange={(value, option) => {
|
74
77
|
const model = value.split('/').slice(1).join('/');
|
75
78
|
onChange?.({ model, provider: (option as unknown as ModelOption).provider });
|
76
79
|
}}
|
77
80
|
options={options}
|
78
|
-
popupClassName={styles.popup}
|
79
81
|
popupMatchSelectWidth={false}
|
80
82
|
value={`${value?.provider}/${value?.model}`}
|
81
83
|
/>
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import {
|
2
|
+
AiProviderDetailItem,
|
2
3
|
AiProviderRuntimeState,
|
3
4
|
AiProviderSortMap,
|
4
5
|
CreateAiProviderParams,
|
@@ -10,7 +11,7 @@ export interface IAiProviderService {
|
|
10
11
|
|
11
12
|
deleteAiProvider: (id: string) => Promise<any>;
|
12
13
|
|
13
|
-
getAiProviderById: (id: string) => Promise<
|
14
|
+
getAiProviderById: (id: string) => Promise<AiProviderDetailItem | undefined>;
|
14
15
|
|
15
16
|
getAiProviderList: () => Promise<any>;
|
16
17
|
|
@@ -10,7 +10,7 @@ const FETCH_KNOWLEDGE_BASE_LIST_KEY = 'FETCH_KNOWLEDGE_BASE';
|
|
10
10
|
const FETCH_KNOWLEDGE_BASE_ITEM_KEY = 'FETCH_KNOWLEDGE_BASE_ITEM';
|
11
11
|
|
12
12
|
export interface KnowledgeBaseCrudAction {
|
13
|
-
createNewKnowledgeBase: (params: CreateKnowledgeBaseParams) => Promise<
|
13
|
+
createNewKnowledgeBase: (params: CreateKnowledgeBaseParams) => Promise<string>;
|
14
14
|
internal_toggleKnowledgeBaseLoading: (id: string, loading: boolean) => void;
|
15
15
|
refreshKnowledgeBaseList: () => Promise<void>;
|
16
16
|
|
@@ -28,8 +28,11 @@ export const createCrudSlice: StateCreator<
|
|
28
28
|
KnowledgeBaseCrudAction
|
29
29
|
> = (set, get) => ({
|
30
30
|
createNewKnowledgeBase: async (params) => {
|
31
|
-
await knowledgeBaseService.createKnowledgeBase(params);
|
31
|
+
const id = await knowledgeBaseService.createKnowledgeBase(params);
|
32
|
+
|
32
33
|
await get().refreshKnowledgeBaseList();
|
34
|
+
|
35
|
+
return id;
|
33
36
|
},
|
34
37
|
internal_toggleKnowledgeBaseLoading: (id, loading) => {
|
35
38
|
set(
|
@@ -58,8 +61,22 @@ export const createCrudSlice: StateCreator<
|
|
58
61
|
},
|
59
62
|
|
60
63
|
useFetchKnowledgeBaseItem: (id) =>
|
61
|
-
useClientDataSWR<KnowledgeBaseItem | undefined>(
|
62
|
-
|
64
|
+
useClientDataSWR<KnowledgeBaseItem | undefined>(
|
65
|
+
[FETCH_KNOWLEDGE_BASE_ITEM_KEY, id],
|
66
|
+
() => knowledgeBaseService.getKnowledgeBaseById(id),
|
67
|
+
{
|
68
|
+
onSuccess: (item) => {
|
69
|
+
if (!item) return;
|
70
|
+
|
71
|
+
set({
|
72
|
+
activeKnowledgeBaseId: id,
|
73
|
+
activeKnowledgeBaseItems: {
|
74
|
+
...get().activeKnowledgeBaseItems,
|
75
|
+
[id]: item,
|
76
|
+
},
|
77
|
+
});
|
78
|
+
},
|
79
|
+
},
|
63
80
|
),
|
64
81
|
|
65
82
|
useFetchKnowledgeBaseList: (params = {}) =>
|
@@ -1,5 +1,8 @@
|
|
1
|
+
import { KnowledgeBaseItem } from '@/types/knowledgeBase';
|
2
|
+
|
1
3
|
export interface KnowledgeBaseState {
|
2
4
|
activeKnowledgeBaseId: string | null;
|
5
|
+
activeKnowledgeBaseItems: Record<string, KnowledgeBaseItem>;
|
3
6
|
initKnowledgeBaseList: boolean;
|
4
7
|
knowledgeBaseLoadingIds: string[];
|
5
8
|
knowledgeBaseRenamingId?: string | null;
|
@@ -7,6 +10,7 @@ export interface KnowledgeBaseState {
|
|
7
10
|
|
8
11
|
export const initialKnowledgeBaseState: KnowledgeBaseState = {
|
9
12
|
activeKnowledgeBaseId: null,
|
13
|
+
activeKnowledgeBaseItems: {},
|
10
14
|
initKnowledgeBaseList: false,
|
11
15
|
knowledgeBaseLoadingIds: [],
|
12
16
|
};
|
@@ -2,6 +2,13 @@ import { KnowledgeBaseStoreState } from '@/store/knowledgeBase/initialState';
|
|
2
2
|
|
3
3
|
const activeKnowledgeBaseId = (s: KnowledgeBaseStoreState) => s.activeKnowledgeBaseId;
|
4
4
|
|
5
|
+
const getKnowledgeBaseById = (id: string) => (s: KnowledgeBaseStoreState) =>
|
6
|
+
s.activeKnowledgeBaseItems[id];
|
7
|
+
|
8
|
+
const getKnowledgeBaseNameById = (id: string) => (s: KnowledgeBaseStoreState) =>
|
9
|
+
getKnowledgeBaseById(id)(s)?.name;
|
10
|
+
|
5
11
|
export const knowledgeBaseSelectors = {
|
6
12
|
activeKnowledgeBaseId,
|
13
|
+
getKnowledgeBaseNameById,
|
7
14
|
};
|