@lobehub/lobehub 2.0.0-next.97 → 2.0.0-next.99
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/.console-log-whitelist.json +14 -0
- package/.github/workflows/check-console-log.yml +117 -0
- package/.github/workflows/desktop-pr-build.yml +4 -4
- package/.github/workflows/release-desktop-beta.yml +4 -4
- package/.github/workflows/release.yml +1 -1
- package/.github/workflows/test.yml +5 -5
- package/CHANGELOG.md +58 -0
- package/apps/desktop/src/main/services/__tests__/fileSrv.test.ts +603 -0
- package/changelog/v1.json +21 -0
- package/codecov.yml +1 -0
- package/docs/development/database-schema.dbml +1 -0
- package/e2e/package.json +1 -1
- package/locales/ar/file.json +9 -11
- package/locales/ar/plugin.json +34 -22
- package/locales/ar/tool.json +8 -0
- package/locales/bg-BG/file.json +8 -10
- package/locales/bg-BG/plugin.json +34 -22
- package/locales/bg-BG/tool.json +8 -0
- package/locales/de-DE/file.json +9 -11
- package/locales/de-DE/plugin.json +34 -22
- package/locales/de-DE/tool.json +8 -0
- package/locales/en-US/file.json +12 -14
- package/locales/en-US/plugin.json +34 -22
- package/locales/en-US/tool.json +8 -0
- package/locales/es-ES/file.json +7 -9
- package/locales/es-ES/plugin.json +34 -22
- package/locales/es-ES/tool.json +8 -0
- package/locales/fa-IR/file.json +9 -11
- package/locales/fa-IR/plugin.json +34 -22
- package/locales/fa-IR/tool.json +8 -0
- package/locales/fr-FR/file.json +6 -8
- package/locales/fr-FR/plugin.json +34 -22
- package/locales/fr-FR/tool.json +8 -0
- package/locales/it-IT/file.json +8 -10
- package/locales/it-IT/plugin.json +34 -22
- package/locales/it-IT/tool.json +8 -0
- package/locales/ja-JP/file.json +10 -12
- package/locales/ja-JP/plugin.json +34 -22
- package/locales/ja-JP/tool.json +8 -0
- package/locales/ko-KR/file.json +8 -10
- package/locales/ko-KR/plugin.json +34 -22
- package/locales/ko-KR/tool.json +8 -0
- package/locales/nl-NL/file.json +8 -10
- package/locales/nl-NL/plugin.json +34 -22
- package/locales/nl-NL/tool.json +8 -0
- package/locales/pl-PL/file.json +7 -9
- package/locales/pl-PL/plugin.json +34 -22
- package/locales/pl-PL/tool.json +8 -0
- package/locales/pt-BR/file.json +7 -9
- package/locales/pt-BR/plugin.json +34 -22
- package/locales/pt-BR/tool.json +8 -0
- package/locales/ru-RU/file.json +9 -11
- package/locales/ru-RU/plugin.json +34 -22
- package/locales/ru-RU/tool.json +8 -0
- package/locales/tr-TR/file.json +8 -10
- package/locales/tr-TR/plugin.json +34 -22
- package/locales/tr-TR/tool.json +8 -0
- package/locales/vi-VN/file.json +9 -11
- package/locales/vi-VN/plugin.json +34 -22
- package/locales/vi-VN/tool.json +8 -0
- package/locales/zh-CN/file.json +10 -12
- package/locales/zh-CN/plugin.json +34 -22
- package/locales/zh-CN/tool.json +8 -0
- package/locales/zh-TW/file.json +10 -12
- package/locales/zh-TW/plugin.json +34 -22
- package/locales/zh-TW/tool.json +8 -0
- package/package.json +3 -2
- package/packages/database/migrations/0047_add_slug_document.sql +6 -0
- package/packages/database/migrations/meta/0047_snapshot.json +7891 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/core/migrations.json +16 -7
- package/packages/database/src/models/__tests__/document.test.ts +149 -0
- package/packages/database/src/models/chunk.ts +3 -1
- package/packages/database/src/models/document.ts +10 -4
- package/packages/database/src/schemas/file.ts +7 -1
- package/packages/model-bank/src/aiModels/qwen.ts +5 -3
- package/packages/model-runtime/src/core/openaiCompatibleFactory/index.ts +21 -21
- package/packages/obervability-otel/package.json +2 -2
- package/packages/prompts/src/prompts/knowledgeBaseQA/__snapshots__/formatFileContents.test.ts.snap +75 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/__snapshots__/formatNoSearchResults.test.ts.snap +45 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/__snapshots__/formatSearchResults.test.ts.snap +82 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/formatFileContents.test.ts +118 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/formatFileContents.ts +31 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/formatNoSearchResults.test.ts +25 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/formatNoSearchResults.ts +13 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/formatSearchResults.test.ts +191 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/formatSearchResults.ts +50 -0
- package/packages/prompts/src/prompts/knowledgeBaseQA/index.ts +6 -0
- package/packages/types/src/rag.ts +13 -4
- package/scripts/checkConsoleLog.mts +148 -0
- package/scripts/prebuild.mts +5 -5
- package/src/app/[variants]/(main)/changelog/index.tsx +1 -1
- package/src/app/[variants]/(main)/settings/_layout/Desktop/index.tsx +20 -16
- package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +6 -3
- package/src/app/[variants]/(main)/settings/provider/(list)/index.tsx +3 -2
- package/src/app/[variants]/(main)/settings/provider/detail/index.tsx +14 -4
- package/src/app/[variants]/desktopRouter.config.tsx +23 -0
- package/src/app/[variants]/mobileRouter.config.tsx +23 -0
- package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +2 -2
- package/src/features/ChatInput/ActionBar/Token/TokenTagForGroupChat.tsx +2 -2
- package/src/features/ChatList/Messages/Group/Tool/Inspector/ToolTitle.tsx +5 -23
- package/src/features/ChatList/Messages/Tool/Inspector/ToolTitle.tsx +5 -25
- package/src/features/KnowledgeManager/DocumentExplorer/NoteEditorModal.tsx +0 -20
- package/src/features/KnowledgeManager/DocumentExplorer/index.tsx +3 -3
- package/src/features/KnowledgeManager/FileExplorer/MasonryFileItem/index.tsx +0 -20
- package/src/features/KnowledgeManager/Header/AddButton.tsx +0 -1
- package/src/features/KnowledgeManager/Header/NewNoteButton.tsx +1 -1
- package/src/features/KnowledgeManager/Header/TogglePanelButton.tsx +2 -2
- package/src/features/KnowledgeManager/Home/UploadEntries.tsx +2 -2
- package/src/features/KnowledgeManager/Home/index.tsx +4 -4
- package/src/features/PluginsUI/Render/BuiltinType/index.tsx +1 -1
- package/src/features/User/UserPanel/useMenu.tsx +7 -3
- package/src/helpers/toolEngineering/index.test.ts +3 -3
- package/src/helpers/toolEngineering/index.ts +17 -4
- package/src/libs/trpc/client/lambda.ts +0 -6
- package/src/locales/default/file.ts +11 -13
- package/src/locales/default/plugin.ts +34 -22
- package/src/locales/default/tool.ts +13 -5
- package/src/server/routers/lambda/chunk.ts +168 -41
- package/src/services/chat/chat.test.ts +3 -3
- package/src/services/chat/index.ts +2 -2
- package/src/services/rag.ts +6 -2
- package/src/store/chat/agents/__tests__/createAgentExecutors/helpers/testExecutor.ts +1 -4
- package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +11 -0
- package/src/store/chat/slices/aiChat/actions/__tests__/rag.test.ts +0 -87
- package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +2 -69
- package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +0 -2
- package/src/store/chat/slices/aiChat/actions/rag.ts +0 -47
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +8 -69
- package/src/store/chat/slices/builtinTool/actions/index.ts +4 -1
- package/src/store/chat/slices/builtinTool/actions/knowledgeBase.ts +174 -0
- package/src/store/chat/slices/operation/types.ts +1 -0
- package/src/store/chat/slices/thread/action.test.ts +0 -1
- package/src/store/chat/slices/thread/action.ts +0 -1
- package/src/tools/executionRuntimes.ts +3 -0
- package/src/tools/identifiers.ts +13 -0
- package/src/tools/index.ts +7 -0
- package/src/tools/knowledge-base/ExecutionRuntime/index.ts +96 -0
- package/src/tools/knowledge-base/Render/ReadKnowledge/FileCard.tsx +135 -0
- package/src/tools/knowledge-base/Render/ReadKnowledge/index.tsx +27 -0
- package/src/tools/knowledge-base/Render/SearchKnowledgeBase/Item/index.tsx +54 -0
- package/src/tools/knowledge-base/Render/SearchKnowledgeBase/Item/style.ts +51 -0
- package/src/tools/knowledge-base/Render/SearchKnowledgeBase/index.tsx +23 -0
- package/src/tools/knowledge-base/Render/index.ts +7 -0
- package/src/tools/knowledge-base/index.ts +64 -0
- package/src/tools/knowledge-base/systemRole.ts +102 -0
- package/src/tools/knowledge-base/type.ts +25 -0
- package/src/tools/local-system/Intervention/WriteFile/index.tsx +1 -1
- package/src/tools/renders.ts +4 -0
- package/src/store/chat/agents/createToolEngine.ts +0 -22
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useResponsive, useTheme } from 'antd-style';
|
|
4
|
+
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
|
4
5
|
import { memo, useEffect, useRef } from 'react';
|
|
5
6
|
import { Flexbox } from 'react-layout-kit';
|
|
6
7
|
import { useSearchParams } from 'react-router-dom';
|
|
@@ -13,7 +14,6 @@ import SettingsContent from '../SettingsContent';
|
|
|
13
14
|
import { LayoutProps } from '../type';
|
|
14
15
|
import Header from './Header';
|
|
15
16
|
import SideBar from './SideBar';
|
|
16
|
-
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
|
17
17
|
|
|
18
18
|
const Layout = memo<LayoutProps>(() => {
|
|
19
19
|
const ref = useRef<HTMLDivElement | null>(null);
|
|
@@ -22,21 +22,23 @@ const Layout = memo<LayoutProps>(() => {
|
|
|
22
22
|
|
|
23
23
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
24
24
|
|
|
25
|
-
const [activeTabState, setActiveTabState] = useMergedState(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
25
|
+
const [activeTabState, setActiveTabState] = useMergedState(
|
|
26
|
+
{
|
|
27
|
+
active: (searchParams.get('active') as SettingsTabs)
|
|
28
|
+
? (searchParams.get('active') as SettingsTabs)
|
|
29
|
+
: SettingsTabs.Common,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
onChange: (obj: { active: SettingsTabs; provider?: string }) => {
|
|
33
|
+
if (obj.provider) {
|
|
34
|
+
setSearchParams({ active: obj.active, provider: obj.provider });
|
|
35
|
+
} else {
|
|
36
|
+
searchParams.delete('provider');
|
|
37
|
+
setSearchParams({ active: obj.active });
|
|
38
|
+
}
|
|
39
|
+
},
|
|
38
40
|
},
|
|
39
|
-
|
|
41
|
+
);
|
|
40
42
|
|
|
41
43
|
const setActiveTab = (tab: SettingsTabs) => {
|
|
42
44
|
if (tab === SettingsTabs.Provider) {
|
|
@@ -57,7 +59,9 @@ const Layout = memo<LayoutProps>(() => {
|
|
|
57
59
|
};
|
|
58
60
|
}, []);
|
|
59
61
|
|
|
60
|
-
const category =
|
|
62
|
+
const category = (
|
|
63
|
+
<CategoryContent activeTab={activeTabState.active} onMenuSelect={setActiveTab} />
|
|
64
|
+
);
|
|
61
65
|
|
|
62
66
|
return (
|
|
63
67
|
<Flexbox
|
|
@@ -33,9 +33,12 @@ const ProviderCard = memo<ProviderCardProps>(
|
|
|
33
33
|
return (
|
|
34
34
|
<Flexbox className={cx(styles.container)} gap={24}>
|
|
35
35
|
<Flexbox gap={12} padding={16} width={'100%'}>
|
|
36
|
-
<div
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
<div
|
|
37
|
+
onClick={() => {
|
|
38
|
+
onProviderSelect(id);
|
|
39
|
+
}}
|
|
40
|
+
style={{ cursor: 'pointer' }}
|
|
41
|
+
>
|
|
39
42
|
<Flexbox gap={12} width={'100%'}>
|
|
40
43
|
<Flexbox align={'center'} horizontal justify={'space-between'}>
|
|
41
44
|
{source === 'builtin' ? (
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import { useSearchParams } from 'react-router-dom';
|
|
5
|
+
|
|
3
6
|
import { isCustomBranding } from '@/const/version';
|
|
4
7
|
|
|
5
8
|
import DesktopLayout from '../_layout/Desktop';
|
|
6
9
|
import MobileLayout from '../_layout/Mobile';
|
|
7
10
|
import ProviderDetailPage from '../detail';
|
|
8
11
|
import Footer from './Footer';
|
|
9
|
-
import { useMemo, useState } from 'react';
|
|
10
|
-
import { useSearchParams } from 'react-router-dom';
|
|
11
12
|
|
|
12
13
|
const Page = (props: { mobile?: boolean }) => {
|
|
13
14
|
const [SearchParams, setSearchParams] = useSearchParams();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import dynamic from 'next/dynamic';
|
|
2
|
+
|
|
2
3
|
import Loading from '@/components/Loading/BrandTextLoading';
|
|
3
4
|
|
|
4
5
|
const NewAPI = dynamic(() => import('./newapi'), { loading: () => <Loading />, ssr: false });
|
|
@@ -7,17 +8,26 @@ const VertexAI = dynamic(() => import('./vertexai'), { loading: () => <Loading /
|
|
|
7
8
|
const GitHub = dynamic(() => import('./github'), { loading: () => <Loading />, ssr: false });
|
|
8
9
|
const Ollama = dynamic(() => import('./ollama'), { loading: () => <Loading />, ssr: false });
|
|
9
10
|
const ComfyUI = dynamic(() => import('./comfyui'), { loading: () => <Loading />, ssr: false });
|
|
10
|
-
const Cloudflare = dynamic(() => import('./cloudflare'), {
|
|
11
|
+
const Cloudflare = dynamic(() => import('./cloudflare'), {
|
|
12
|
+
loading: () => <Loading />,
|
|
13
|
+
ssr: false,
|
|
14
|
+
});
|
|
11
15
|
const Bedrock = dynamic(() => import('./bedrock'), { loading: () => <Loading />, ssr: false });
|
|
12
16
|
const AzureAI = dynamic(() => import('./azureai'), { loading: () => <Loading />, ssr: false });
|
|
13
17
|
const Azure = dynamic(() => import('./azure'), { loading: () => <Loading />, ssr: false });
|
|
14
|
-
const ProviderGrid = dynamic(() => import('../(list)/ProviderGrid'), {
|
|
15
|
-
|
|
18
|
+
const ProviderGrid = dynamic(() => import('../(list)/ProviderGrid'), {
|
|
19
|
+
loading: () => <Loading />,
|
|
20
|
+
ssr: false,
|
|
21
|
+
});
|
|
22
|
+
const DefaultPage = dynamic(() => import('./default/ProviderDetialPage'), {
|
|
23
|
+
loading: () => <Loading />,
|
|
24
|
+
ssr: false,
|
|
25
|
+
});
|
|
16
26
|
|
|
17
27
|
type ProviderDetailPageProps = {
|
|
18
28
|
id?: string | null;
|
|
19
29
|
onProviderSelect: (provider: string) => void;
|
|
20
|
-
}
|
|
30
|
+
};
|
|
21
31
|
|
|
22
32
|
const ProviderDetailPage = (props: ProviderDetailPageProps) => {
|
|
23
33
|
const { id, onProviderSelect } = props;
|
|
@@ -40,6 +40,16 @@ const ChatLayout = dynamic(() => import('./(main)/chat/_layout/Desktop'), {
|
|
|
40
40
|
ssr: false,
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
+
// Changelog components
|
|
44
|
+
const ChangelogPage = dynamic(() => import('./(main)/changelog/index').then((m) => m.DesktopPage), {
|
|
45
|
+
loading: () => <Loading />,
|
|
46
|
+
ssr: false,
|
|
47
|
+
});
|
|
48
|
+
const ChangelogLayout = dynamic(() => import('./(main)/changelog/_layout/Desktop'), {
|
|
49
|
+
loading: () => <Loading />,
|
|
50
|
+
ssr: false,
|
|
51
|
+
});
|
|
52
|
+
|
|
43
53
|
// Discover List components
|
|
44
54
|
const DesktopHomePage = dynamic(
|
|
45
55
|
() => import('./(main)/discover/(list)/(home)/index').then((m) => m.DesktopHomePage),
|
|
@@ -256,6 +266,7 @@ const KnowledgeErrorBoundary = createErrorBoundary('/knowledge');
|
|
|
256
266
|
const SettingsErrorBoundary = createErrorBoundary('/settings');
|
|
257
267
|
const ImageErrorBoundary = createErrorBoundary('/image');
|
|
258
268
|
const ProfileErrorBoundary = createErrorBoundary('/profile');
|
|
269
|
+
const ChangelogErrorBoundary = createErrorBoundary('/changelog');
|
|
259
270
|
const RootErrorBoundary = createErrorBoundary('/chat'); // Root level falls back to chat
|
|
260
271
|
|
|
261
272
|
// Root layout wrapper component
|
|
@@ -455,6 +466,18 @@ export const createDesktopRouter = (locale: Locales) =>
|
|
|
455
466
|
path: 'profile',
|
|
456
467
|
},
|
|
457
468
|
|
|
469
|
+
// changelog routes
|
|
470
|
+
{
|
|
471
|
+
children: [
|
|
472
|
+
{
|
|
473
|
+
element: <ChangelogPage />,
|
|
474
|
+
index: true,
|
|
475
|
+
},
|
|
476
|
+
],
|
|
477
|
+
element: <ChangelogLayout locale={locale} />,
|
|
478
|
+
errorElement: <ChangelogErrorBoundary />,
|
|
479
|
+
path: 'changelog',
|
|
480
|
+
},
|
|
458
481
|
// Default route - redirect to chat
|
|
459
482
|
{
|
|
460
483
|
index: true,
|
|
@@ -41,6 +41,15 @@ const ChatLayout = dynamic(() => import('./(main)/chat/_layout/Mobile'), {
|
|
|
41
41
|
ssr: false,
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
// Changelog components
|
|
45
|
+
const ChangelogPage = dynamic(() => import('./(main)/changelog/index').then((m) => m.MobilePage), {
|
|
46
|
+
loading: () => <Loading />,
|
|
47
|
+
ssr: false,
|
|
48
|
+
});
|
|
49
|
+
const ChangelogLayout = dynamic(() => import('./(main)/changelog/_layout/Mobile'), {
|
|
50
|
+
loading: () => <Loading />,
|
|
51
|
+
ssr: false,
|
|
52
|
+
});
|
|
44
53
|
// Discover List components
|
|
45
54
|
const MobileHomePage = dynamic(
|
|
46
55
|
() => import('./(main)/discover/(list)/(home)/index').then((m) => m.MobileHomePage),
|
|
@@ -272,6 +281,7 @@ const createErrorBoundary = (resetPath: string) => {
|
|
|
272
281
|
// Create error boundaries for each route
|
|
273
282
|
const ChatErrorBoundary = createErrorBoundary('/chat');
|
|
274
283
|
const DiscoverErrorBoundary = createErrorBoundary('/discover');
|
|
284
|
+
const ChangelogErrorBoundary = createErrorBoundary('/changelog');
|
|
275
285
|
const KnowledgeErrorBoundary = createErrorBoundary('/knowledge');
|
|
276
286
|
const SettingsErrorBoundary = createErrorBoundary('/settings');
|
|
277
287
|
const ImageErrorBoundary = createErrorBoundary('/image');
|
|
@@ -499,6 +509,19 @@ export const createMobileRouter = (locale: Locales) =>
|
|
|
499
509
|
path: 'me',
|
|
500
510
|
},
|
|
501
511
|
|
|
512
|
+
// changelog routes
|
|
513
|
+
{
|
|
514
|
+
children: [
|
|
515
|
+
{
|
|
516
|
+
element: <ChangelogPage />,
|
|
517
|
+
index: true,
|
|
518
|
+
},
|
|
519
|
+
],
|
|
520
|
+
element: <ChangelogLayout locale={locale} />,
|
|
521
|
+
errorElement: <ChangelogErrorBoundary />,
|
|
522
|
+
path: 'changelog',
|
|
523
|
+
},
|
|
524
|
+
|
|
502
525
|
// Default route - redirect to chat
|
|
503
526
|
{
|
|
504
527
|
index: true,
|
|
@@ -6,7 +6,7 @@ import { memo, useMemo } from 'react';
|
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { createAgentToolsEngine } from '@/helpers/toolEngineering';
|
|
10
10
|
import { useModelContextWindowTokens } from '@/hooks/useModelContextWindowTokens';
|
|
11
11
|
import { useModelSupportToolUse } from '@/hooks/useModelSupportToolUse';
|
|
12
12
|
import { useTokenCount } from '@/hooks/useTokenCount';
|
|
@@ -57,7 +57,7 @@ const Token = memo<TokenTagProps>(({ total: messageString }) => {
|
|
|
57
57
|
const pluginIds = useAgentStore(agentSelectors.currentAgentPlugins);
|
|
58
58
|
|
|
59
59
|
const toolsString = useToolStore((s) => {
|
|
60
|
-
const toolsEngine =
|
|
60
|
+
const toolsEngine = createAgentToolsEngine({ model, provider });
|
|
61
61
|
|
|
62
62
|
const { tools, enabledToolIds } = toolsEngine.generateToolsDetailed({
|
|
63
63
|
model,
|
|
@@ -7,7 +7,7 @@ import { memo, useMemo } from 'react';
|
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { createAgentToolsEngine } from '@/helpers/toolEngineering';
|
|
11
11
|
import { useModelContextWindowTokens } from '@/hooks/useModelContextWindowTokens';
|
|
12
12
|
import { useModelSupportToolUse } from '@/hooks/useModelSupportToolUse';
|
|
13
13
|
import { useTokenCount } from '@/hooks/useTokenCount';
|
|
@@ -76,7 +76,7 @@ const TokenTagForGroupChat = memo<TokenTagForGroupChatProps>(({ total: messageSt
|
|
|
76
76
|
const pluginIds = allGroupPlugins.map((plugin) => plugin.id);
|
|
77
77
|
|
|
78
78
|
const toolsString = useToolStore((s) => {
|
|
79
|
-
const toolsEngine =
|
|
79
|
+
const toolsEngine = createAgentToolsEngine({ model, provider });
|
|
80
80
|
|
|
81
81
|
const { tools, enabledToolIds } = toolsEngine.generateToolsDetailed({
|
|
82
82
|
model,
|
|
@@ -2,15 +2,14 @@ import { Icon } from '@lobehub/ui';
|
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
3
|
import isEqual from 'fast-deep-equal';
|
|
4
4
|
import { ChevronRight } from 'lucide-react';
|
|
5
|
-
import { memo
|
|
5
|
+
import { memo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
9
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
10
10
|
import { toolSelectors } from '@/store/tool/selectors';
|
|
11
11
|
import { shinyTextStylish } from '@/styles/loading';
|
|
12
|
-
import {
|
|
13
|
-
import { WebBrowsingManifest } from '@/tools/web-browsing';
|
|
12
|
+
import { builtinToolIdentifiers } from '@/tools/identifiers';
|
|
14
13
|
|
|
15
14
|
import BuiltinPluginTitle from './BuiltinPluginTitle';
|
|
16
15
|
|
|
@@ -49,33 +48,16 @@ const ToolTitle = memo<ToolTitleProps>(
|
|
|
49
48
|
|
|
50
49
|
const pluginMeta = useToolStore(toolSelectors.getMetaById(identifier), isEqual);
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
() => [
|
|
54
|
-
{
|
|
55
|
-
apiName: t(`search.apiName.${apiName}`, apiName),
|
|
56
|
-
id: WebBrowsingManifest.identifier,
|
|
57
|
-
title: t('search.title'),
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
apiName: t(`localSystem.apiName.${apiName}`, apiName),
|
|
61
|
-
id: LocalSystemManifest.identifier,
|
|
62
|
-
title: t('localSystem.title'),
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
[],
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
const builtinPluginTitle = plugins.find((item) => item.id === identifier);
|
|
69
|
-
|
|
70
|
-
if (!!builtinPluginTitle) {
|
|
51
|
+
if (builtinToolIdentifiers.includes(identifier)) {
|
|
71
52
|
return (
|
|
72
53
|
<BuiltinPluginTitle
|
|
73
|
-
{
|
|
54
|
+
apiName={t(`builtins.${identifier}.apiName.${apiName}`, apiName)}
|
|
74
55
|
identifier={identifier}
|
|
75
56
|
index={index}
|
|
76
57
|
isExpanded={isExpanded}
|
|
77
58
|
isLoading={isLoading}
|
|
78
59
|
messageId={messageId}
|
|
60
|
+
title={t(`builtins.${identifier}.title`, identifier)}
|
|
79
61
|
toolCallId={toolCallId}
|
|
80
62
|
/>
|
|
81
63
|
);
|
|
@@ -2,15 +2,14 @@ import { Icon } from '@lobehub/ui';
|
|
|
2
2
|
import { createStyles } from 'antd-style';
|
|
3
3
|
import isEqual from 'fast-deep-equal';
|
|
4
4
|
import { ChevronRight } from 'lucide-react';
|
|
5
|
-
import { memo
|
|
5
|
+
import { memo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
9
|
import { pluginHelpers, useToolStore } from '@/store/tool';
|
|
10
10
|
import { toolSelectors } from '@/store/tool/selectors';
|
|
11
11
|
import { shinyTextStylish } from '@/styles/loading';
|
|
12
|
-
import {
|
|
13
|
-
import { WebBrowsingManifest } from '@/tools/web-browsing';
|
|
12
|
+
import { builtinToolIdentifiers } from '@/tools/identifiers';
|
|
14
13
|
|
|
15
14
|
import BuiltinPluginTitle from './BuiltinPluginTitle';
|
|
16
15
|
|
|
@@ -43,33 +42,14 @@ const ToolTitle = memo<ToolTitleProps>(({ identifier, messageId, index, apiName,
|
|
|
43
42
|
|
|
44
43
|
const pluginMeta = useToolStore(toolSelectors.getMetaById(identifier), isEqual);
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
() => [
|
|
48
|
-
{
|
|
49
|
-
apiName: t(`search.apiName.${apiName}`, apiName),
|
|
50
|
-
// icon: <Icon icon={Globe} size={13} />,
|
|
51
|
-
id: WebBrowsingManifest.identifier,
|
|
52
|
-
title: t('search.title'),
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
apiName: t(`localSystem.apiName.${apiName}`, apiName),
|
|
56
|
-
// icon: <Icon icon={Laptop} size={13} />,
|
|
57
|
-
id: LocalSystemManifest.identifier,
|
|
58
|
-
title: t('localSystem.title'),
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
|
-
[],
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
const builtinPluginTitle = plugins.find((item) => item.id === identifier);
|
|
65
|
-
|
|
66
|
-
if (!!builtinPluginTitle) {
|
|
45
|
+
if (builtinToolIdentifiers.includes(identifier)) {
|
|
67
46
|
return (
|
|
68
47
|
<BuiltinPluginTitle
|
|
69
|
-
{
|
|
48
|
+
apiName={t(`builtins.${identifier}.apiName.${apiName}`, apiName)}
|
|
70
49
|
identifier={identifier}
|
|
71
50
|
index={index}
|
|
72
51
|
messageId={messageId}
|
|
52
|
+
title={t(`builtins.${identifier}.title`, identifier)}
|
|
73
53
|
toolCallId={toolCallId}
|
|
74
54
|
/>
|
|
75
55
|
);
|
|
@@ -143,40 +143,20 @@ const NoteEditorModal = memo<NoteEditorModalProps>(
|
|
|
143
143
|
const handleOpenChange = (isOpen: boolean) => {
|
|
144
144
|
// When modal opens, load document content if in edit mode
|
|
145
145
|
if (isOpen && documentId && editor) {
|
|
146
|
-
console.log('[NoteEditorModal] Loading content:', {
|
|
147
|
-
cachedEditorDataPreview: cachedEditorData
|
|
148
|
-
? JSON.stringify(cachedEditorData).slice(0, 100)
|
|
149
|
-
: null,
|
|
150
|
-
cachedEditorDataType: typeof cachedEditorData,
|
|
151
|
-
documentId,
|
|
152
|
-
documentTitle,
|
|
153
|
-
hasCachedEditorData: !!cachedEditorData,
|
|
154
|
-
});
|
|
155
|
-
|
|
156
146
|
// If editorData is already cached (from list), use it directly
|
|
157
147
|
if (cachedEditorData) {
|
|
158
|
-
console.log('[NoteEditorModal] Using cached editorData', cachedEditorData);
|
|
159
148
|
setNoteTitle(documentTitle || '');
|
|
160
149
|
editor.setDocument('json', JSON.stringify(cachedEditorData));
|
|
161
150
|
return;
|
|
162
151
|
}
|
|
163
152
|
|
|
164
153
|
// Otherwise, fetch full content from API
|
|
165
|
-
console.log('[NoteEditorModal] Fetching from API');
|
|
166
154
|
documentService
|
|
167
155
|
.getDocumentById(documentId)
|
|
168
156
|
.then((doc) => {
|
|
169
157
|
if (doc && doc.content) {
|
|
170
158
|
setNoteTitle(doc.title || doc.filename || '');
|
|
171
159
|
|
|
172
|
-
console.log('[NoteEditorModal] Fetched doc.editorData:', {
|
|
173
|
-
editorDataPreview: doc.editorData
|
|
174
|
-
? JSON.stringify(doc.editorData).slice(0, 100)
|
|
175
|
-
: null,
|
|
176
|
-
editorDataType: typeof doc.editorData,
|
|
177
|
-
hasEditorData: !!doc.editorData,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
160
|
editor.setDocument('json', doc.editorData);
|
|
181
161
|
}
|
|
182
162
|
})
|
|
@@ -228,7 +228,7 @@ const DocumentExplorer = memo<DocumentExplorerProps>(({ knowledgeBaseId, documen
|
|
|
228
228
|
<SearchBar
|
|
229
229
|
allowClear
|
|
230
230
|
onChange={(e) => setSearchKeywords(e.target.value)}
|
|
231
|
-
placeholder={t('
|
|
231
|
+
placeholder={t('searchPagePlaceholder')}
|
|
232
232
|
style={{ flex: 1 }}
|
|
233
233
|
value={searchKeywords}
|
|
234
234
|
variant={'borderless'}
|
|
@@ -236,7 +236,7 @@ const DocumentExplorer = memo<DocumentExplorerProps>(({ knowledgeBaseId, documen
|
|
|
236
236
|
<ActionIcon
|
|
237
237
|
icon={PlusIcon}
|
|
238
238
|
onClick={handleNewDocument}
|
|
239
|
-
title={t('header.
|
|
239
|
+
title={t('header.newPageButton')}
|
|
240
240
|
/>
|
|
241
241
|
</div>
|
|
242
242
|
<div className={styles.documentList}>
|
|
@@ -252,7 +252,7 @@ const DocumentExplorer = memo<DocumentExplorerProps>(({ knowledgeBaseId, documen
|
|
|
252
252
|
Footer: () => (
|
|
253
253
|
<Center style={{ paddingBlock: 16 }}>
|
|
254
254
|
<Text style={{ fontSize: 12 }} type={'secondary'}>
|
|
255
|
-
{t('documentList.
|
|
255
|
+
{t('documentList.pageCount', { count: filteredDocuments.length })}
|
|
256
256
|
</Text>
|
|
257
257
|
</Center>
|
|
258
258
|
),
|
|
@@ -177,19 +177,6 @@ const MasonryFileItem = memo<MasonryFileItemProps>(
|
|
|
177
177
|
const isMarkdown = isMarkdownFile(name, fileType);
|
|
178
178
|
const isNote = isCustomNote(fileType);
|
|
179
179
|
|
|
180
|
-
// Debug: Log editorData for notes
|
|
181
|
-
useEffect(() => {
|
|
182
|
-
if (isNote) {
|
|
183
|
-
console.log('[MasonryFileItem] Note item:', {
|
|
184
|
-
editorDataPreview: editorData ? JSON.stringify(editorData).slice(0, 100) : null,
|
|
185
|
-
editorDataType: typeof editorData,
|
|
186
|
-
hasEditorData: !!editorData,
|
|
187
|
-
id,
|
|
188
|
-
name,
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}, [isNote, id, name, editorData]);
|
|
192
|
-
|
|
193
180
|
const cardRef = useRef<HTMLDivElement>(null);
|
|
194
181
|
const [isInView, setIsInView] = useState(false);
|
|
195
182
|
|
|
@@ -288,12 +275,6 @@ const MasonryFileItem = memo<MasonryFileItemProps>(
|
|
|
288
275
|
)}
|
|
289
276
|
onClick={() => {
|
|
290
277
|
if (isNote) {
|
|
291
|
-
console.log('[MasonryFileItem] Opening note modal with:', {
|
|
292
|
-
editorDataType: typeof editorData,
|
|
293
|
-
hasEditorData: !!editorData,
|
|
294
|
-
id,
|
|
295
|
-
name,
|
|
296
|
-
});
|
|
297
278
|
setIsNoteModalOpen(true);
|
|
298
279
|
} else {
|
|
299
280
|
onOpen(id);
|
|
@@ -384,7 +365,6 @@ const MasonryFileItem = memo<MasonryFileItemProps>(
|
|
|
384
365
|
editorData={editorData}
|
|
385
366
|
knowledgeBaseId={knowledgeBaseId}
|
|
386
367
|
onClose={() => {
|
|
387
|
-
console.log('[MasonryFileItem] Closing note modal');
|
|
388
368
|
setIsNoteModalOpen(false);
|
|
389
369
|
}}
|
|
390
370
|
open={isNoteModalOpen}
|
|
@@ -22,7 +22,7 @@ const NewNoteButton = ({ knowledgeBaseId }: { knowledgeBaseId?: string }) => {
|
|
|
22
22
|
return (
|
|
23
23
|
<>
|
|
24
24
|
<Button icon={FilePenLine} onClick={handleOpen} type="primary">
|
|
25
|
-
{t('header.
|
|
25
|
+
{t('header.newPageButton')}
|
|
26
26
|
</Button>
|
|
27
27
|
|
|
28
28
|
<NoteEditorModal knowledgeBaseId={knowledgeBaseId} onClose={handleClose} open={isModalOpen} />
|
|
@@ -17,13 +17,13 @@ export const TOOGLE_PANEL_BUTTON_ID = 'toggle-panel-button';
|
|
|
17
17
|
const TogglePanelButton = memo(() => {
|
|
18
18
|
const hotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.ToggleLeftPanel));
|
|
19
19
|
|
|
20
|
-
const { t } = useTranslation(['file'
|
|
20
|
+
const { t } = useTranslation(['file']);
|
|
21
21
|
|
|
22
22
|
const showFilePanel = useGlobalStore(systemStatusSelectors.showFilePanel);
|
|
23
23
|
const updateSystemStatus = useGlobalStore((s) => s.updateSystemStatus);
|
|
24
24
|
|
|
25
25
|
return (
|
|
26
|
-
<Tooltip hotkey={hotkey} title={t('toggleLeftPanel
|
|
26
|
+
<Tooltip hotkey={hotkey} title={t('toggleLeftPanel')}>
|
|
27
27
|
<ActionIcon
|
|
28
28
|
icon={showFilePanel ? PanelLeftClose : PanelLeftOpen}
|
|
29
29
|
id={TOOGLE_PANEL_BUTTON_ID}
|
|
@@ -97,7 +97,7 @@ const UploadEntries = memo<UploadEntriesProps>(({ knowledgeBaseId }) => {
|
|
|
97
97
|
const newDoc = await createDocument({
|
|
98
98
|
content: '',
|
|
99
99
|
knowledgeBaseId,
|
|
100
|
-
title: t('home.uploadEntries.
|
|
100
|
+
title: t('home.uploadEntries.newPage.title'),
|
|
101
101
|
});
|
|
102
102
|
// Navigate to the newly created document
|
|
103
103
|
// The KnowledgeHomePage will automatically set category to 'documents' when it detects the id param
|
|
@@ -137,7 +137,7 @@ const UploadEntries = memo<UploadEntriesProps>(({ knowledgeBaseId }) => {
|
|
|
137
137
|
<div className={styles.grid}>
|
|
138
138
|
{/* Create New Note */}
|
|
139
139
|
<Flexbox className={styles.card} onClick={handleCreateNote} padding={16}>
|
|
140
|
-
<span className={styles.actionTitle}>{t('home.uploadEntries.
|
|
140
|
+
<span className={styles.actionTitle}>{t('home.uploadEntries.newPage.title')}</span>
|
|
141
141
|
<div className={styles.glow} style={{ background: theme.purple }} />
|
|
142
142
|
<FileTypeIcon
|
|
143
143
|
className={styles.icon}
|
|
@@ -165,7 +165,7 @@ const Home = memo<HomeProps>(({ knowledgeBaseId, onOpenFile }) => {
|
|
|
165
165
|
</div>
|
|
166
166
|
)}
|
|
167
167
|
|
|
168
|
-
{/* Recent
|
|
168
|
+
{/* Recent Pages Section */}
|
|
169
169
|
{(isLoading || topRecentDocuments.length > 0) && (
|
|
170
170
|
<div
|
|
171
171
|
className={styles.section}
|
|
@@ -179,7 +179,7 @@ const Home = memo<HomeProps>(({ knowledgeBaseId, onOpenFile }) => {
|
|
|
179
179
|
<div className={styles.sectionTitleWrapper}>
|
|
180
180
|
<Text className={styles.sectionTitle} style={{ marginBottom: 0 }}>
|
|
181
181
|
<FileTextIcon size={18} />
|
|
182
|
-
{t('home.
|
|
182
|
+
{t('home.recentPages')}
|
|
183
183
|
</Text>
|
|
184
184
|
<div
|
|
185
185
|
className={styles.sectionActions}
|
|
@@ -192,9 +192,9 @@ const Home = memo<HomeProps>(({ knowledgeBaseId, onOpenFile }) => {
|
|
|
192
192
|
items: [
|
|
193
193
|
{
|
|
194
194
|
key: 'all-documents',
|
|
195
|
-
label: t('menu.
|
|
195
|
+
label: t('menu.allPages'),
|
|
196
196
|
onClick: () => {
|
|
197
|
-
setActiveKey(FilesTabs.
|
|
197
|
+
setActiveKey(FilesTabs.Pages);
|
|
198
198
|
},
|
|
199
199
|
},
|
|
200
200
|
],
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
} from 'lucide-react';
|
|
18
18
|
import { PropsWithChildren, memo } from 'react';
|
|
19
19
|
import { useTranslation } from 'react-i18next';
|
|
20
|
-
import { Link } from 'react-router-dom';
|
|
21
20
|
import { Flexbox } from 'react-layout-kit';
|
|
21
|
+
import { Link } from 'react-router-dom';
|
|
22
22
|
|
|
23
23
|
import type { MenuProps } from '@/components/Menu';
|
|
24
24
|
import { enableAuth } from '@/const/auth';
|
|
@@ -135,7 +135,11 @@ export const useMenu = () => {
|
|
|
135
135
|
icon: <Icon icon={Cloudy} />,
|
|
136
136
|
key: 'cloud',
|
|
137
137
|
label: (
|
|
138
|
-
<a
|
|
138
|
+
<a
|
|
139
|
+
href={`${OFFICIAL_URL}?utm_source=${UTM_SOURCE}`}
|
|
140
|
+
rel="noopener noreferrer"
|
|
141
|
+
target="_blank"
|
|
142
|
+
>
|
|
139
143
|
{t('userPanel.cloud', { name: LOBE_CHAT_CLOUD })}
|
|
140
144
|
</a>
|
|
141
145
|
),
|
|
@@ -148,7 +152,7 @@ export const useMenu = () => {
|
|
|
148
152
|
{t('changelog')}
|
|
149
153
|
</a>
|
|
150
154
|
) : (
|
|
151
|
-
<Link to="/changelog
|
|
155
|
+
<Link to="/changelog">{t('changelog')}</Link>
|
|
152
156
|
),
|
|
153
157
|
},
|
|
154
158
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LobeChatPluginManifest } from '@lobehub/chat-plugin-sdk';
|
|
2
2
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { createAgentToolsEngine, createToolsEngine, getEnabledTools } from './index';
|
|
5
5
|
|
|
6
6
|
// Mock the store and helper dependencies
|
|
7
7
|
vi.mock('@/store/tool', () => ({
|
|
@@ -137,7 +137,7 @@ describe('toolEngineering', () => {
|
|
|
137
137
|
|
|
138
138
|
describe('createChatToolsEngine', () => {
|
|
139
139
|
it('should include web browsing tool as default when no tools are provided', () => {
|
|
140
|
-
const toolsEngine =
|
|
140
|
+
const toolsEngine = createAgentToolsEngine({
|
|
141
141
|
model: 'gpt-4',
|
|
142
142
|
provider: 'openai',
|
|
143
143
|
});
|
|
@@ -152,7 +152,7 @@ describe('toolEngineering', () => {
|
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
it('should include web browsing tool alongside user-provided tools', () => {
|
|
155
|
-
const toolsEngine =
|
|
155
|
+
const toolsEngine = createAgentToolsEngine({
|
|
156
156
|
model: 'gpt-4',
|
|
157
157
|
provider: 'openai',
|
|
158
158
|
});
|