@lobehub/lobehub 2.0.0-next.98 → 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.
Files changed (96) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/apps/desktop/src/main/services/__tests__/fileSrv.test.ts +603 -0
  3. package/changelog/v1.json +9 -0
  4. package/codecov.yml +1 -0
  5. package/locales/ar/plugin.json +34 -22
  6. package/locales/ar/tool.json +8 -0
  7. package/locales/bg-BG/plugin.json +34 -22
  8. package/locales/bg-BG/tool.json +8 -0
  9. package/locales/de-DE/plugin.json +34 -22
  10. package/locales/de-DE/tool.json +8 -0
  11. package/locales/en-US/plugin.json +34 -22
  12. package/locales/en-US/tool.json +8 -0
  13. package/locales/es-ES/plugin.json +34 -22
  14. package/locales/es-ES/tool.json +8 -0
  15. package/locales/fa-IR/plugin.json +34 -22
  16. package/locales/fa-IR/tool.json +8 -0
  17. package/locales/fr-FR/plugin.json +34 -22
  18. package/locales/fr-FR/tool.json +8 -0
  19. package/locales/it-IT/plugin.json +34 -22
  20. package/locales/it-IT/tool.json +8 -0
  21. package/locales/ja-JP/plugin.json +34 -22
  22. package/locales/ja-JP/tool.json +8 -0
  23. package/locales/ko-KR/plugin.json +34 -22
  24. package/locales/ko-KR/tool.json +8 -0
  25. package/locales/nl-NL/plugin.json +34 -22
  26. package/locales/nl-NL/tool.json +8 -0
  27. package/locales/pl-PL/plugin.json +34 -22
  28. package/locales/pl-PL/tool.json +8 -0
  29. package/locales/pt-BR/plugin.json +34 -22
  30. package/locales/pt-BR/tool.json +8 -0
  31. package/locales/ru-RU/plugin.json +34 -22
  32. package/locales/ru-RU/tool.json +8 -0
  33. package/locales/tr-TR/plugin.json +34 -22
  34. package/locales/tr-TR/tool.json +8 -0
  35. package/locales/vi-VN/plugin.json +34 -22
  36. package/locales/vi-VN/tool.json +8 -0
  37. package/locales/zh-CN/plugin.json +34 -22
  38. package/locales/zh-CN/tool.json +8 -0
  39. package/locales/zh-TW/plugin.json +34 -22
  40. package/locales/zh-TW/tool.json +8 -0
  41. package/package.json +1 -1
  42. package/packages/database/src/models/__tests__/document.test.ts +149 -0
  43. package/packages/database/src/models/chunk.ts +3 -1
  44. package/packages/database/src/models/document.ts +8 -2
  45. package/packages/prompts/src/prompts/knowledgeBaseQA/__snapshots__/formatFileContents.test.ts.snap +75 -0
  46. package/packages/prompts/src/prompts/knowledgeBaseQA/__snapshots__/formatNoSearchResults.test.ts.snap +45 -0
  47. package/packages/prompts/src/prompts/knowledgeBaseQA/__snapshots__/formatSearchResults.test.ts.snap +82 -0
  48. package/packages/prompts/src/prompts/knowledgeBaseQA/formatFileContents.test.ts +118 -0
  49. package/packages/prompts/src/prompts/knowledgeBaseQA/formatFileContents.ts +31 -0
  50. package/packages/prompts/src/prompts/knowledgeBaseQA/formatNoSearchResults.test.ts +25 -0
  51. package/packages/prompts/src/prompts/knowledgeBaseQA/formatNoSearchResults.ts +13 -0
  52. package/packages/prompts/src/prompts/knowledgeBaseQA/formatSearchResults.test.ts +191 -0
  53. package/packages/prompts/src/prompts/knowledgeBaseQA/formatSearchResults.ts +50 -0
  54. package/packages/prompts/src/prompts/knowledgeBaseQA/index.ts +6 -0
  55. package/packages/types/src/rag.ts +13 -4
  56. package/src/features/ChatInput/ActionBar/Token/TokenTag.tsx +2 -2
  57. package/src/features/ChatInput/ActionBar/Token/TokenTagForGroupChat.tsx +2 -2
  58. package/src/features/ChatList/Messages/Group/Tool/Inspector/ToolTitle.tsx +5 -23
  59. package/src/features/ChatList/Messages/Tool/Inspector/ToolTitle.tsx +5 -25
  60. package/src/features/PluginsUI/Render/BuiltinType/index.tsx +1 -1
  61. package/src/helpers/toolEngineering/index.test.ts +3 -3
  62. package/src/helpers/toolEngineering/index.ts +17 -4
  63. package/src/libs/trpc/client/lambda.ts +0 -6
  64. package/src/locales/default/plugin.ts +34 -22
  65. package/src/locales/default/tool.ts +13 -5
  66. package/src/server/routers/lambda/chunk.ts +168 -41
  67. package/src/services/chat/chat.test.ts +3 -3
  68. package/src/services/chat/index.ts +2 -2
  69. package/src/services/rag.ts +6 -2
  70. package/src/store/chat/slices/aiChat/actions/__tests__/conversationLifecycle.test.ts +11 -0
  71. package/src/store/chat/slices/aiChat/actions/__tests__/rag.test.ts +0 -87
  72. package/src/store/chat/slices/aiChat/actions/__tests__/streamingExecutor.test.ts +2 -69
  73. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +0 -2
  74. package/src/store/chat/slices/aiChat/actions/rag.ts +0 -47
  75. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +8 -69
  76. package/src/store/chat/slices/builtinTool/actions/index.ts +4 -1
  77. package/src/store/chat/slices/builtinTool/actions/knowledgeBase.ts +174 -0
  78. package/src/store/chat/slices/operation/types.ts +1 -0
  79. package/src/store/chat/slices/thread/action.test.ts +0 -1
  80. package/src/store/chat/slices/thread/action.ts +0 -1
  81. package/src/tools/executionRuntimes.ts +3 -0
  82. package/src/tools/identifiers.ts +13 -0
  83. package/src/tools/index.ts +7 -0
  84. package/src/tools/knowledge-base/ExecutionRuntime/index.ts +96 -0
  85. package/src/tools/knowledge-base/Render/ReadKnowledge/FileCard.tsx +135 -0
  86. package/src/tools/knowledge-base/Render/ReadKnowledge/index.tsx +27 -0
  87. package/src/tools/knowledge-base/Render/SearchKnowledgeBase/Item/index.tsx +54 -0
  88. package/src/tools/knowledge-base/Render/SearchKnowledgeBase/Item/style.ts +51 -0
  89. package/src/tools/knowledge-base/Render/SearchKnowledgeBase/index.tsx +23 -0
  90. package/src/tools/knowledge-base/Render/index.ts +7 -0
  91. package/src/tools/knowledge-base/index.ts +64 -0
  92. package/src/tools/knowledge-base/systemRole.ts +102 -0
  93. package/src/tools/knowledge-base/type.ts +25 -0
  94. package/src/tools/local-system/Intervention/WriteFile/index.tsx +1 -1
  95. package/src/tools/renders.ts +4 -0
  96. package/src/store/chat/agents/createToolEngine.ts +0 -22
@@ -4,6 +4,7 @@ import { isDesktop } from '@/const/version';
4
4
 
5
5
  import { ArtifactsManifest } from './artifacts';
6
6
  import { CodeInterpreterManifest } from './code-interpreter';
7
+ import { KnowledgeBaseManifest } from './knowledge-base';
7
8
  import { LocalSystemManifest } from './local-system';
8
9
  import { WebBrowsingManifest } from './web-browsing';
9
10
 
@@ -30,4 +31,10 @@ export const builtinTools: LobeBuiltinTool[] = [
30
31
  manifest: CodeInterpreterManifest,
31
32
  type: 'builtin',
32
33
  },
34
+ {
35
+ hidden: true,
36
+ identifier: KnowledgeBaseManifest.identifier,
37
+ manifest: KnowledgeBaseManifest,
38
+ type: 'builtin',
39
+ },
33
40
  ];
@@ -0,0 +1,96 @@
1
+ import { formatSearchResults, promptFileContents, promptNoSearchResults } from '@lobechat/prompts';
2
+ import { BuiltinServerRuntimeOutput } from '@lobechat/types';
3
+
4
+ import { ragService } from '@/services/rag';
5
+
6
+ import { ReadKnowledgeState, SearchKnowledgeBaseArgs, SearchKnowledgeBaseState } from '../type';
7
+
8
+ export interface ReadKnowledgeArgs {
9
+ fileIds: string[];
10
+ }
11
+
12
+ export class KnowledgeBaseExecutionRuntime {
13
+ /**
14
+ * Search knowledge base and return file summaries with relevant chunks
15
+ */
16
+ async searchKnowledgeBase(
17
+ args: SearchKnowledgeBaseArgs,
18
+ options?: {
19
+ fileIds?: string[];
20
+ knowledgeBaseIds?: string[];
21
+ messageId?: string;
22
+ signal?: AbortSignal;
23
+ },
24
+ ): Promise<BuiltinServerRuntimeOutput> {
25
+ try {
26
+ const { query, topK = 20 } = args;
27
+
28
+ // Call the existing RAG service
29
+ const { chunks, fileResults } = await ragService.semanticSearchForChat(
30
+ { fileIds: options?.fileIds, knowledgeIds: options?.knowledgeBaseIds, query, topK },
31
+ options?.signal,
32
+ );
33
+
34
+ if (chunks.length === 0) {
35
+ const state: SearchKnowledgeBaseState = { chunks: [], fileResults: [], totalResults: 0 };
36
+
37
+ return { content: promptNoSearchResults(query), state, success: true };
38
+ }
39
+
40
+ // Format search results for AI
41
+ const formattedContent = formatSearchResults(fileResults, query);
42
+
43
+ const state: SearchKnowledgeBaseState = { chunks, fileResults, totalResults: chunks.length };
44
+
45
+ return { content: formattedContent, state, success: true };
46
+ } catch (e) {
47
+ return {
48
+ content: `Error searching knowledge base: ${(e as Error).message}`,
49
+ error: e,
50
+ success: false,
51
+ };
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Read full content of specific files from knowledge base
57
+ */
58
+ async readKnowledge(
59
+ args: ReadKnowledgeArgs,
60
+ options?: { signal?: AbortSignal },
61
+ ): Promise<BuiltinServerRuntimeOutput> {
62
+ try {
63
+ const { fileIds } = args;
64
+
65
+ if (!fileIds || fileIds.length === 0) {
66
+ return {
67
+ content: 'Error: No file IDs provided',
68
+ success: false,
69
+ };
70
+ }
71
+
72
+ const fileContents = await ragService.getFileContents(fileIds, options?.signal);
73
+
74
+ const formattedContent = promptFileContents(fileContents);
75
+
76
+ const state: ReadKnowledgeState = {
77
+ files: fileContents.map((file) => ({
78
+ error: file.error,
79
+ fileId: file.fileId,
80
+ filename: file.filename,
81
+ preview: file.preview,
82
+ totalCharCount: file.totalCharCount,
83
+ totalLineCount: file.totalLineCount,
84
+ })),
85
+ };
86
+
87
+ return { content: formattedContent, state, success: true };
88
+ } catch (e) {
89
+ return {
90
+ content: `Error reading knowledge: ${(e as Error).message}`,
91
+ error: e,
92
+ success: false,
93
+ };
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,135 @@
1
+ 'use client';
2
+
3
+ import { Alert, Text } from '@lobehub/ui';
4
+ import { Descriptions } from 'antd';
5
+ import { createStyles } from 'antd-style';
6
+ import { memo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+ import { Flexbox } from 'react-layout-kit';
9
+
10
+ import FileIcon from '@/components/FileIcon';
11
+
12
+ import { FileContentDetail } from '../../type';
13
+
14
+ const useStyles = createStyles(({ token, css }) => {
15
+ return {
16
+ cardBody: css`
17
+ padding-block: 12px 8px;
18
+ padding-inline: 16px;
19
+ `,
20
+ container: css`
21
+ overflow: hidden;
22
+
23
+ min-width: 360px;
24
+ max-width: 360px;
25
+ border: 1px solid ${token.colorBorderSecondary};
26
+ border-radius: 12px;
27
+ `,
28
+ description: css`
29
+ margin-block: 0 4px !important;
30
+ color: ${token.colorTextTertiary};
31
+ `,
32
+ footer: css`
33
+ padding-block: 8px;
34
+ padding-inline: 16px;
35
+ border-radius: 8px;
36
+
37
+ text-align: center;
38
+
39
+ background-color: ${token.colorFillQuaternary};
40
+ `,
41
+ footerText: css`
42
+ font-size: 12px !important;
43
+ color: ${token.colorTextTertiary} !important;
44
+ `,
45
+ icon: css`
46
+ color: ${token.colorTextSecondary};
47
+ `,
48
+ preview: css`
49
+ overflow: hidden;
50
+
51
+ max-height: 80px;
52
+ padding: 8px;
53
+ border-radius: 6px;
54
+
55
+ font-family: ${token.fontFamilyCode};
56
+ font-size: 12px;
57
+ line-height: 1.5;
58
+ color: ${token.colorTextSecondary};
59
+ `,
60
+ title: css`
61
+ overflow: hidden;
62
+ display: -webkit-box;
63
+ -webkit-box-orient: vertical;
64
+ -webkit-line-clamp: 1;
65
+
66
+ margin-block-end: 0;
67
+ `,
68
+ titleRow: css`
69
+ color: ${token.colorText};
70
+ `,
71
+ };
72
+ });
73
+
74
+ interface FileCardProps {
75
+ file: FileContentDetail;
76
+ }
77
+
78
+ const FileCard = memo<FileCardProps>(({ file }) => {
79
+ const { t } = useTranslation('tool');
80
+ const { styles } = useStyles();
81
+
82
+ if (file.error) {
83
+ return (
84
+ <Flexbox className={styles.container} gap={8}>
85
+ <Flexbox className={styles.cardBody} gap={8}>
86
+ <Flexbox align={'center'} className={styles.titleRow} gap={8} horizontal>
87
+ <FileIcon fileName={file.filename} size={16} />
88
+ <div className={styles.title}>{file.filename}</div>
89
+ </Flexbox>
90
+ </Flexbox>
91
+ <div className={styles.footer}>
92
+ <Alert message={file.error} type={'error'} variant={'borderless'} />
93
+ </div>
94
+ </Flexbox>
95
+ );
96
+ }
97
+
98
+ return (
99
+ <Flexbox className={styles.container} justify={'space-between'}>
100
+ <Flexbox className={styles.cardBody} gap={8}>
101
+ <Flexbox align={'center'} className={styles.titleRow} gap={8} horizontal>
102
+ <FileIcon fileName={file.filename} size={16} />
103
+ <div className={styles.title}>{file.filename}</div>
104
+ </Flexbox>
105
+ {file.preview && (
106
+ <Text className={styles.preview} ellipsis={{ rows: 4 }}>
107
+ {file.preview}...
108
+ </Text>
109
+ )}
110
+ </Flexbox>
111
+ <div className={styles.footer}>
112
+ <Descriptions
113
+ classNames={{
114
+ content: styles.footerText,
115
+ label: styles.footerText,
116
+ }}
117
+ column={2}
118
+ items={[
119
+ {
120
+ children: file.totalCharCount?.toLocaleString(),
121
+ label: t('lobe-knowledge-base.readKnowledge.meta.chars'),
122
+ },
123
+ {
124
+ children: file.totalLineCount?.toLocaleString(),
125
+ label: t('lobe-knowledge-base.readKnowledge.meta.lines'),
126
+ },
127
+ ]}
128
+ size="small"
129
+ />
130
+ </div>
131
+ </Flexbox>
132
+ );
133
+ });
134
+
135
+ export default FileCard;
@@ -0,0 +1,27 @@
1
+ import { BuiltinRenderProps } from '@lobechat/types';
2
+ import { memo } from 'react';
3
+ import { Flexbox } from 'react-layout-kit';
4
+
5
+ import { ReadKnowledgeArgs } from '../../ExecutionRuntime';
6
+ import { ReadKnowledgeState } from '../../type';
7
+ import FileCard from './FileCard';
8
+
9
+ const ReadKnowledge = memo<BuiltinRenderProps<ReadKnowledgeArgs, ReadKnowledgeState>>(
10
+ ({ pluginState }) => {
11
+ const { files } = pluginState || {};
12
+
13
+ if (!files || files.length === 0) {
14
+ return null;
15
+ }
16
+
17
+ return (
18
+ <Flexbox gap={12} horizontal style={{ flexWrap: 'wrap' }}>
19
+ {files.map((file) => (
20
+ <FileCard file={file} key={file.fileId} />
21
+ ))}
22
+ </Flexbox>
23
+ );
24
+ },
25
+ );
26
+
27
+ export default ReadKnowledge;
@@ -0,0 +1,54 @@
1
+ import { FileSearchResult } from '@lobechat/types';
2
+ import { Text, Tooltip } from '@lobehub/ui';
3
+ import { memo } from 'react';
4
+ import { Center, Flexbox } from 'react-layout-kit';
5
+
6
+ import FileIcon from '@/components/FileIcon';
7
+ import { useIsMobile } from '@/hooks/useIsMobile';
8
+ import { useChatStore } from '@/store/chat';
9
+
10
+ import { useStyles } from './style';
11
+
12
+ export interface FileItemProps extends FileSearchResult {
13
+ index: number;
14
+ }
15
+
16
+ const FileItem = memo<FileItemProps>(({ fileId, fileName, relevanceScore, topChunks }) => {
17
+ const { styles, cx } = useStyles();
18
+ const openFilePreview = useChatStore((s) => s.openFilePreview);
19
+
20
+ const isMobile = useIsMobile();
21
+
22
+ // Use the first chunk for preview
23
+ const firstChunk = topChunks[0];
24
+
25
+ return (
26
+ <Flexbox
27
+ align={'center'}
28
+ className={cx(styles.container, isMobile && styles.mobile)}
29
+ gap={4}
30
+ horizontal
31
+ key={fileId}
32
+ onClick={(e) => {
33
+ e.stopPropagation();
34
+ if (firstChunk) {
35
+ openFilePreview({
36
+ chunkId: firstChunk.id,
37
+ chunkText: firstChunk.text,
38
+ fileId,
39
+ });
40
+ }
41
+ }}
42
+ >
43
+ <FileIcon fileName={fileName} size={20} variant={'raw'} />
44
+ <Flexbox gap={12} horizontal justify={'space-between'} style={{ maxWidth: 200 }}>
45
+ <Text ellipsis>{fileName}</Text>
46
+ <Tooltip title={`Relevance: ${(relevanceScore * 100).toFixed(1)}%`}>
47
+ <Center className={styles.badge}>{relevanceScore.toFixed(2)}</Center>
48
+ </Tooltip>
49
+ </Flexbox>
50
+ </Flexbox>
51
+ );
52
+ });
53
+
54
+ export default FileItem;
@@ -0,0 +1,51 @@
1
+ import { createStyles } from 'antd-style';
2
+ import { lighten } from 'polished';
3
+
4
+ export const useStyles = createStyles(({ css, token, isDarkMode }) => ({
5
+ badge: css`
6
+ padding-block: 4px;
7
+ padding-inline: 6px;
8
+ border-radius: 2222px;
9
+
10
+ font-size: 12px;
11
+ line-height: 12px;
12
+ color: ${token.colorTextSecondary};
13
+
14
+ background: ${token.colorFillSecondary};
15
+ `,
16
+
17
+ container: css`
18
+ cursor: pointer;
19
+
20
+ width: fit-content;
21
+ padding-block: 6px;
22
+ padding-inline: 8px;
23
+ padding-inline-end: 12px;
24
+ border-radius: 8px;
25
+
26
+ color: ${token.colorText};
27
+
28
+ background: ${lighten(0.1, token.colorBgElevated)};
29
+ box-shadow: ${token.boxShadowTertiary};
30
+
31
+ transition: all 0.2s;
32
+
33
+ &:hover {
34
+ background: ${isDarkMode ? lighten(0.15, token.colorBgElevated) : ''};
35
+ box-shadow: ${token.boxShadowSecondary};
36
+ }
37
+ `,
38
+ filename: css`
39
+ overflow: hidden;
40
+ display: -webkit-box;
41
+ -webkit-box-orient: vertical;
42
+ -webkit-line-clamp: 1;
43
+
44
+ font-size: 12px;
45
+ text-overflow: ellipsis;
46
+ `,
47
+
48
+ mobile: css`
49
+ width: 100%;
50
+ `,
51
+ }));
@@ -0,0 +1,23 @@
1
+ import { BuiltinRenderProps } from '@lobechat/types';
2
+ import { memo } from 'react';
3
+ import { Flexbox } from 'react-layout-kit';
4
+
5
+ import { SearchKnowledgeBaseArgs, SearchKnowledgeBaseState } from '@/tools/knowledge-base/type';
6
+
7
+ import FileItem from './Item';
8
+
9
+ const SearchKnowledgeBase = memo<
10
+ BuiltinRenderProps<SearchKnowledgeBaseArgs, SearchKnowledgeBaseState>
11
+ >(({ pluginState }) => {
12
+ const { fileResults } = pluginState || {};
13
+
14
+ return (
15
+ <Flexbox gap={8} horizontal wrap={'wrap'}>
16
+ {fileResults?.map((file, index) => {
17
+ return <FileItem index={index} key={file.fileId} {...file} />;
18
+ })}
19
+ </Flexbox>
20
+ );
21
+ });
22
+
23
+ export default SearchKnowledgeBase;
@@ -0,0 +1,7 @@
1
+ import ReadKnowledge from './ReadKnowledge';
2
+ import SearchKnowledgeBase from './SearchKnowledgeBase';
3
+
4
+ export const KnowledgeBaseRenders = {
5
+ readKnowledge: ReadKnowledge,
6
+ searchKnowledgeBase: SearchKnowledgeBase,
7
+ };
@@ -0,0 +1,64 @@
1
+ import { BuiltinToolManifest } from '@lobechat/types';
2
+
3
+ import { systemPrompt } from './systemRole';
4
+
5
+ export const KnowledgeBaseApiName = {
6
+ readKnowledge: 'readKnowledge',
7
+ searchKnowledgeBase: 'searchKnowledgeBase',
8
+ };
9
+
10
+ export const KnowledgeBaseManifest: BuiltinToolManifest = {
11
+ api: [
12
+ {
13
+ description:
14
+ 'Search through knowledge base using semantic vector search to find relevant files and chunks. Returns a summary of matching files with their relevance scores and brief excerpts. Use this first to discover which files contain relevant information. IMPORTANT: Since this uses vector-based search, always resolve pronouns and references to concrete entities (e.g., use "authentication system" instead of "it").',
15
+ name: KnowledgeBaseApiName.searchKnowledgeBase,
16
+ parameters: {
17
+ properties: {
18
+ query: {
19
+ description:
20
+ 'The search query to find relevant information. Be specific and use concrete entities. IMPORTANT: Resolve all pronouns and references (like "it", "that", "this") to actual entity names before searching, as this uses semantic vector search which works best with concrete terms.',
21
+ type: 'string',
22
+ },
23
+ topK: {
24
+ default: 15,
25
+ description:
26
+ 'Number of top relevant chunks to return (default: 15). Each file will include the most relevant chunks.',
27
+ maximum: 100,
28
+ minimum: 5,
29
+ type: 'number',
30
+ },
31
+ },
32
+ required: ['query'],
33
+ type: 'object',
34
+ },
35
+ },
36
+ {
37
+ description:
38
+ 'Read the full content of specific files from the knowledge base. Use this after searchKnowledgeBase to get complete information from relevant files. You can read multiple files at once.',
39
+ name: KnowledgeBaseApiName.readKnowledge,
40
+ parameters: {
41
+ properties: {
42
+ fileIds: {
43
+ description:
44
+ 'Array of file IDs to read. Get these IDs from searchKnowledgeBase results.',
45
+ items: {
46
+ type: 'string',
47
+ },
48
+ type: 'array',
49
+ },
50
+ },
51
+ required: ['fileIds'],
52
+ type: 'object',
53
+ },
54
+ },
55
+ ],
56
+ identifier: 'lobe-knowledge-base',
57
+ meta: {
58
+ avatar: '📚',
59
+ description: 'Search and retrieve information from knowledge bases',
60
+ title: 'Knowledge Base',
61
+ },
62
+ systemRole: systemPrompt,
63
+ type: 'builtin',
64
+ };
@@ -0,0 +1,102 @@
1
+ export const systemPrompt = `You have access to a Knowledge Base tool with powerful semantic search and document retrieval capabilities. You can search through knowledge bases to find relevant information and read the full content of files.
2
+
3
+ <core_capabilities>
4
+ 1. Search through knowledge base using semantic search (searchKnowledgeBase)
5
+ 2. Read the full content of specific files from the knowledge base (readKnowledge)
6
+ </core_capabilities>
7
+
8
+ <workflow>
9
+ 1. Understand the user's information need or question
10
+ 2. Formulate a clear, specific search query
11
+ 3. Use searchKnowledgeBase to discover relevant files and chunks
12
+ 4. Review search results to identify the most relevant files
13
+ 5. Use readKnowledge to retrieve full content from selected files
14
+ 6. Synthesize information and answer the user's question
15
+ 7. Always cite source files when providing information
16
+ </workflow>
17
+
18
+ <tool_selection_guidelines>
19
+ - **searchKnowledgeBase**: Use this first to discover which files contain relevant information
20
+ - Uses semantic vector search to find relevant content
21
+ - Returns file names, relevance scores, and brief excerpts
22
+ - Helps you decide which files to read in full
23
+ - You can adjust topK parameter (5-100, default: 15) based on how many results you need
24
+ - **IMPORTANT**: Since this uses vector-based semantic search, always resolve references and use concrete entities in your query
25
+ - BAD: "What does it do?" or "Tell me about that feature"
26
+ - GOOD: "What does the authentication system do?" or "Tell me about the JWT authentication feature"
27
+
28
+ - **readKnowledge**: Use this after searching to get complete file content
29
+ - Can read multiple files at once by providing their file IDs
30
+ - Get file IDs from searchKnowledgeBase results
31
+ - Provides complete context from the selected files
32
+ </tool_selection_guidelines>
33
+
34
+ <search_strategy_guidelines>
35
+ - **Coreference Resolution**: Always resolve pronouns and references to concrete entities before searching
36
+ - Replace "it", "that", "this", "them" with the actual entity names
37
+ - Use full names instead of abbreviations when first searching
38
+ - Include relevant context in the query itself
39
+ - Examples:
40
+ - User asks: "What are its features?" (after discussing "authentication system")
41
+ - Search query should be: "authentication system features" (NOT "its features")
42
+ - User asks: "How does that work?"
43
+ - Search query should include the specific topic being discussed
44
+ - Formulate clear and specific search queries that capture the core information need
45
+ - For broad topics, start with a general query then refine if needed
46
+ - For specific questions, use precise terminology
47
+ - You can perform multiple searches with different queries or perspectives if needed
48
+ - Adjust topK based on result quality - increase if you need more context, decrease for focused searches
49
+ - Review the relevance scores and excerpts to select the most pertinent files
50
+ </search_strategy_guidelines>
51
+
52
+ <reading_strategy_guidelines>
53
+ - Read only the files that are most relevant to avoid information overload
54
+ - You can read multiple files at once if they all contain relevant information
55
+ - Prioritize files with higher relevance scores from search results
56
+ - If search results show many relevant files, consider reading them in batches
57
+ </reading_strategy_guidelines>
58
+
59
+ <citation_requirements>
60
+ - Always cite the source files when providing information
61
+ - Reference file names clearly in your response
62
+ - If specific information comes from a particular file, mention it explicitly
63
+ - Help users understand which knowledge base files support your answers
64
+ </citation_requirements>
65
+
66
+ <response_format>
67
+ When providing information from the knowledge base:
68
+ 1. Start with a direct answer to the user's question when possible
69
+ 2. Provide relevant details and context from the knowledge base files
70
+ 3. Clearly cite which files the information comes from
71
+ 4. If information is insufficient or not found, inform the user clearly
72
+ 5. Suggest related searches if the initial search doesn't yield good results
73
+ </response_format>
74
+
75
+ <best_practices>
76
+ - Always start with searchKnowledgeBase before reading files
77
+ - Don't read files blindly - review search results first
78
+ - Be selective about which files to read based on relevance
79
+ - If no relevant information is found, clearly inform the user
80
+ - Suggest alternative search queries if initial results are poor
81
+ - Respect the knowledge base's scope - it may not contain all information
82
+ - Combine information from multiple files when appropriate
83
+ - Maintain accuracy - only cite information actually present in the files
84
+ </best_practices>
85
+
86
+ <error_handling>
87
+ - If search returns no results:
88
+ 1. Try reformulating the query with different keywords or broader terms
89
+ 2. Suggest alternative search approaches to the user
90
+ 3. Inform the user if the topic appears to be outside the knowledge base's scope
91
+
92
+ - If file reading fails:
93
+ 1. Inform the user which files couldn't be accessed
94
+ 2. Work with successfully retrieved files if any
95
+ 3. Suggest searching again if necessary
96
+
97
+ - If search results are ambiguous:
98
+ 1. Ask for clarification from the user
99
+ 2. Provide a summary of what types of information were found
100
+ 3. Let the user guide which direction to explore further
101
+ </error_handling>
102
+ `;
@@ -0,0 +1,25 @@
1
+ import { ChatSemanticSearchChunk, FileSearchResult } from '@lobechat/types';
2
+
3
+
4
+ export interface SearchKnowledgeBaseArgs {
5
+ query: string;
6
+ topK?: number;
7
+ }
8
+ export interface SearchKnowledgeBaseState {
9
+ chunks: ChatSemanticSearchChunk[];
10
+ fileResults: FileSearchResult[];
11
+ totalResults: number;
12
+ }
13
+
14
+ export interface FileContentDetail {
15
+ error?: string;
16
+ fileId: string;
17
+ filename: string;
18
+ preview?: string;
19
+ totalCharCount?: number;
20
+ totalLineCount?: number;
21
+ }
22
+
23
+ export interface ReadKnowledgeState {
24
+ files: FileContentDetail[];
25
+ }
@@ -11,7 +11,7 @@ import { LocalFile, LocalFolder } from '@/features/LocalFile';
11
11
 
12
12
  const WriteFile = memo<BuiltinInterventionProps<WriteLocalFileParams>>(({ args }) => {
13
13
  const { t } = useTranslation('tool');
14
- const { base, dir, ext } = path.parse(args.path);
14
+ const { base, dir, ext } = path.parse(args.path || '');
15
15
 
16
16
  // Detect language from file extension
17
17
  const language = useMemo(() => {
@@ -2,6 +2,9 @@ import { BuiltinRender } from '@lobechat/types';
2
2
 
3
3
  import { CodeInterpreterManifest } from './code-interpreter';
4
4
  import CodeInterpreterRender from './code-interpreter/Render';
5
+ // knowledge-base
6
+ import { KnowledgeBaseManifest } from './knowledge-base';
7
+ import { KnowledgeBaseRenders } from './knowledge-base/Render';
5
8
  // local-system
6
9
  import { LocalSystemManifest } from './local-system';
7
10
  import { LocalSystemRenders } from './local-system/Render';
@@ -16,6 +19,7 @@ import { WebBrowsingRenders } from './web-browsing/Render';
16
19
  const BuiltinToolsRenders: Record<string, Record<string, BuiltinRender>> = {
17
20
  [LocalSystemManifest.identifier]: LocalSystemRenders as Record<string, BuiltinRender>,
18
21
  [WebBrowsingManifest.identifier]: WebBrowsingRenders as Record<string, BuiltinRender>,
22
+ [KnowledgeBaseManifest.identifier]: KnowledgeBaseRenders as Record<string, BuiltinRender>,
19
23
  [CodeInterpreterManifest.identifier]: {
20
24
  python: CodeInterpreterRender as BuiltinRender,
21
25
  },
@@ -1,22 +0,0 @@
1
- import { WorkingModel } from '@lobechat/types';
2
-
3
- import { getSearchConfig } from '@/helpers/getSearchConfig';
4
- import { createToolsEngine } from '@/helpers/toolEngineering';
5
- import { WebBrowsingManifest } from '@/tools/web-browsing';
6
-
7
- export const createAgentToolsEngine = (workingModel: WorkingModel) =>
8
- createToolsEngine({
9
- // Add WebBrowsingManifest as default tool
10
- defaultToolIds: [WebBrowsingManifest.identifier],
11
- // Create search-aware enableChecker for this request
12
- enableChecker: ({ pluginId }) => {
13
- // For WebBrowsingManifest, apply search logic
14
- if (pluginId === WebBrowsingManifest.identifier) {
15
- const searchConfig = getSearchConfig(workingModel.model, workingModel.provider);
16
- return searchConfig.useApplicationBuiltinSearchTool;
17
- }
18
-
19
- // For all other plugins, enable by default
20
- return true;
21
- },
22
- });