@lobehub/chat 1.80.5 → 1.81.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +18 -0
- package/package.json +1 -1
- package/packages/electron-client-ipc/src/events/index.ts +6 -2
- package/packages/electron-client-ipc/src/events/remoteServer.ts +28 -0
- package/packages/electron-client-ipc/src/types/index.ts +1 -0
- package/packages/electron-client-ipc/src/types/remoteServer.ts +8 -0
- package/packages/electron-server-ipc/package.json +7 -1
- package/packages/electron-server-ipc/src/ipcClient.ts +54 -20
- package/packages/electron-server-ipc/src/ipcServer.ts +42 -9
- package/packages/web-crawler/src/crawImpl/__tests__/search1api.test.ts +33 -39
- package/packages/web-crawler/src/crawImpl/search1api.ts +1 -7
- package/packages/web-crawler/src/index.ts +1 -0
- package/packages/web-crawler/src/urlRules.ts +3 -1
- package/src/config/aiModels/sensenova.ts +120 -5
- package/src/config/tools.ts +2 -0
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/Debug.tsx +9 -3
- package/src/features/Conversation/Messages/Assistant/Tool/Inspector/PluginState.tsx +21 -0
- package/src/features/Conversation/Messages/Assistant/Tool/Render/Arguments.tsx +1 -1
- package/src/libs/agent-runtime/sensenova/index.ts +17 -4
- package/src/libs/agent-runtime/utils/sensenovaHelpers.test.ts +108 -0
- package/src/libs/agent-runtime/utils/sensenovaHelpers.ts +30 -0
- package/src/locales/default/plugin.ts +1 -0
- package/src/server/routers/tools/{__test__/search.test.ts → search.test.ts} +27 -5
- package/src/server/routers/tools/search.ts +3 -44
- package/src/server/services/search/impls/index.ts +30 -0
- package/src/server/services/search/impls/search1api/index.ts +154 -0
- package/src/server/services/search/impls/search1api/type.ts +81 -0
- package/src/server/{modules/SearXNG.ts → services/search/impls/searxng/client.ts} +32 -2
- package/src/server/{routers/tools/__tests__ → services/search/impls/searxng}/fixtures/searXNG.ts +2 -2
- package/src/server/services/search/impls/searxng/index.test.ts +26 -0
- package/src/server/services/search/impls/searxng/index.ts +62 -0
- package/src/server/services/search/impls/type.ts +11 -0
- package/src/server/services/search/index.ts +59 -0
- package/src/store/chat/slices/builtinTool/actions/index.ts +1 -1
- package/src/store/chat/slices/builtinTool/actions/{searXNG.test.ts → search.test.ts} +30 -55
- package/src/store/chat/slices/builtinTool/actions/{searXNG.ts → search.ts} +25 -32
- package/src/tools/web-browsing/Portal/Search/Footer.tsx +1 -1
- package/src/tools/web-browsing/Portal/Search/ResultList/SearchItem/TitleExtra.tsx +2 -2
- package/src/tools/web-browsing/Portal/Search/ResultList/SearchItem/Video.tsx +9 -7
- package/src/tools/web-browsing/Portal/Search/ResultList/SearchItem/index.tsx +2 -2
- package/src/tools/web-browsing/Portal/Search/ResultList/index.tsx +3 -3
- package/src/tools/web-browsing/Portal/Search/index.tsx +4 -4
- package/src/tools/web-browsing/Portal/index.tsx +3 -1
- package/src/tools/web-browsing/Render/Search/SearchQuery/SearchView.tsx +4 -2
- package/src/tools/web-browsing/Render/Search/SearchQuery/index.tsx +6 -13
- package/src/tools/web-browsing/Render/Search/SearchResult/SearchResultItem.tsx +2 -2
- package/src/tools/web-browsing/Render/Search/SearchResult/index.tsx +5 -5
- package/src/tools/web-browsing/Render/Search/index.tsx +2 -2
- package/src/tools/web-browsing/Render/index.tsx +4 -3
- package/src/tools/web-browsing/components/SearchBar.tsx +4 -6
- package/src/tools/web-browsing/index.ts +54 -60
- package/src/tools/web-browsing/systemRole.ts +22 -13
- package/src/types/tool/search/index.ts +44 -0
- package/src/server/routers/tools/__tests__/search.test.ts +0 -48
- package/src/types/tool/search.ts +0 -48
@@ -4,20 +4,21 @@ import { WebBrowsingApiName } from '@/tools/web-browsing';
|
|
4
4
|
import PageContent from '@/tools/web-browsing/Render/PageContent';
|
5
5
|
import { BuiltinRenderProps } from '@/types/tool';
|
6
6
|
import { CrawlMultiPagesQuery, CrawlPluginState, CrawlSinglePageQuery } from '@/types/tool/crawler';
|
7
|
-
import { SearchContent, SearchQuery,
|
7
|
+
import { SearchContent, SearchQuery, UniformSearchResponse } from '@/types/tool/search';
|
8
8
|
|
9
9
|
import Search from './Search';
|
10
10
|
|
11
11
|
const WebBrowsing = memo<BuiltinRenderProps<SearchContent[]>>(
|
12
12
|
({ messageId, args, pluginState, pluginError, apiName }) => {
|
13
13
|
switch (apiName) {
|
14
|
-
case WebBrowsingApiName.
|
14
|
+
case WebBrowsingApiName.search:
|
15
|
+
case 'searchWithSearXNG': {
|
15
16
|
return (
|
16
17
|
<Search
|
17
18
|
messageId={messageId}
|
18
19
|
pluginError={pluginError}
|
19
20
|
searchQuery={args as SearchQuery}
|
20
|
-
searchResponse={pluginState as
|
21
|
+
searchResponse={pluginState as UniformSearchResponse}
|
21
22
|
/>
|
22
23
|
);
|
23
24
|
}
|
@@ -45,16 +45,14 @@ const SearchBar = memo<SearchBarProps>(
|
|
45
45
|
const [engines, setEngines] = useState(defaultEngines);
|
46
46
|
const [time_range, setTimeRange] = useState(defaultTimeRange);
|
47
47
|
const isMobile = useIsMobile();
|
48
|
-
const [reSearchWithSearXNG] = useChatStore((s) => [s.
|
48
|
+
const [reSearchWithSearXNG] = useChatStore((s) => [s.triggerSearchAgain]);
|
49
49
|
|
50
50
|
const updateAndSearch = async () => {
|
51
51
|
const data: SearchQuery = {
|
52
|
-
optionalParams: {
|
53
|
-
searchCategories: categories,
|
54
|
-
searchEngines: engines,
|
55
|
-
searchTimeRange: time_range,
|
56
|
-
},
|
57
52
|
query,
|
53
|
+
searchCategories: categories,
|
54
|
+
searchEngines: engines,
|
55
|
+
searchTimeRange: time_range,
|
58
56
|
};
|
59
57
|
onSearch?.(data);
|
60
58
|
await reSearchWithSearXNG(messageId, data, { aiSummary });
|
@@ -7,78 +7,72 @@ import { systemPrompt } from './systemRole';
|
|
7
7
|
export const WebBrowsingApiName = {
|
8
8
|
crawlMultiPages: 'crawlMultiPages',
|
9
9
|
crawlSinglePage: 'crawlSinglePage',
|
10
|
-
|
10
|
+
search: 'search',
|
11
11
|
};
|
12
12
|
|
13
13
|
export const WebBrowsingManifest: BuiltinToolManifest = {
|
14
14
|
api: [
|
15
15
|
{
|
16
16
|
description:
|
17
|
-
'
|
18
|
-
name: WebBrowsingApiName.
|
17
|
+
'a search service. Useful for when you need to answer questions about current events. Input should be a search query. Output is a JSON array of the query results',
|
18
|
+
name: WebBrowsingApiName.search,
|
19
19
|
parameters: {
|
20
20
|
properties: {
|
21
|
-
optionalParams: {
|
22
|
-
description: 'The optional parameters for search query',
|
23
|
-
properties: {
|
24
|
-
searchCategories: {
|
25
|
-
description: 'The search categories you can set:',
|
26
|
-
items: {
|
27
|
-
enum: [
|
28
|
-
'files',
|
29
|
-
'general',
|
30
|
-
'images',
|
31
|
-
'it',
|
32
|
-
'map',
|
33
|
-
'music',
|
34
|
-
'news',
|
35
|
-
'science',
|
36
|
-
'social_media',
|
37
|
-
'videos',
|
38
|
-
],
|
39
|
-
type: 'string',
|
40
|
-
},
|
41
|
-
type: 'array',
|
42
|
-
},
|
43
|
-
searchEngines: {
|
44
|
-
description: 'The search engines you can use:',
|
45
|
-
items: {
|
46
|
-
enum: [
|
47
|
-
'google',
|
48
|
-
'bilibili',
|
49
|
-
'bing',
|
50
|
-
'duckduckgo',
|
51
|
-
'npm',
|
52
|
-
'pypi',
|
53
|
-
'github',
|
54
|
-
'arxiv',
|
55
|
-
'google scholar',
|
56
|
-
'z-library',
|
57
|
-
'reddit',
|
58
|
-
'imdb',
|
59
|
-
'brave',
|
60
|
-
'wikipedia',
|
61
|
-
'pinterest',
|
62
|
-
'unsplash',
|
63
|
-
'vimeo',
|
64
|
-
'youtube',
|
65
|
-
],
|
66
|
-
type: 'string',
|
67
|
-
},
|
68
|
-
type: 'array',
|
69
|
-
},
|
70
|
-
searchTimeRange: {
|
71
|
-
description: 'The time range you can set:',
|
72
|
-
enum: ['anytime', 'day', 'week', 'month', 'year'],
|
73
|
-
type: 'string',
|
74
|
-
},
|
75
|
-
},
|
76
|
-
type: 'object',
|
77
|
-
},
|
78
21
|
query: {
|
79
22
|
description: 'The search query',
|
80
23
|
type: 'string',
|
81
24
|
},
|
25
|
+
searchCategories: {
|
26
|
+
description: 'The search categories you can set:',
|
27
|
+
items: {
|
28
|
+
enum: [
|
29
|
+
'files',
|
30
|
+
'general',
|
31
|
+
'images',
|
32
|
+
'it',
|
33
|
+
'map',
|
34
|
+
'music',
|
35
|
+
'news',
|
36
|
+
'science',
|
37
|
+
'social_media',
|
38
|
+
'videos',
|
39
|
+
],
|
40
|
+
type: 'string',
|
41
|
+
},
|
42
|
+
type: 'array',
|
43
|
+
},
|
44
|
+
searchEngines: {
|
45
|
+
description: 'The search engines you can use:',
|
46
|
+
items: {
|
47
|
+
enum: [
|
48
|
+
'google',
|
49
|
+
'bilibili',
|
50
|
+
'bing',
|
51
|
+
'duckduckgo',
|
52
|
+
'npm',
|
53
|
+
'pypi',
|
54
|
+
'github',
|
55
|
+
'arxiv',
|
56
|
+
'google scholar',
|
57
|
+
'z-library',
|
58
|
+
'reddit',
|
59
|
+
'imdb',
|
60
|
+
'brave',
|
61
|
+
'wikipedia',
|
62
|
+
'pinterest',
|
63
|
+
'unsplash',
|
64
|
+
'vimeo',
|
65
|
+
'youtube',
|
66
|
+
],
|
67
|
+
type: 'string',
|
68
|
+
},
|
69
|
+
type: 'array',
|
70
|
+
},
|
71
|
+
searchTimeRange: {
|
72
|
+
description: 'The time range you can set:',
|
73
|
+
enum: ['anytime', 'day', 'week', 'month', 'year'],
|
74
|
+
type: 'string',
|
75
|
+
},
|
82
76
|
},
|
83
77
|
required: ['query'],
|
84
78
|
type: 'object',
|
@@ -3,9 +3,9 @@ export const systemPrompt = (
|
|
3
3
|
) => `You have a Web Information tool with powerful internet access capabilities. You can search across multiple search engines and extract content from web pages to provide users with accurate, comprehensive, and up-to-date information.
|
4
4
|
|
5
5
|
<core_capabilities>
|
6
|
-
1. Search the web using multiple search engines (
|
6
|
+
1. Search the web using multiple search engines (search)
|
7
|
+
2. Retrieve content from multiple webpages simultaneously (crawlMultiPages)
|
7
8
|
2. Retrieve content from a specific webpage (crawlSinglePage)
|
8
|
-
3. Retrieve content from multiple webpages simultaneously (crawlMultiPages)
|
9
9
|
</core_capabilities>
|
10
10
|
|
11
11
|
<workflow>
|
@@ -18,8 +18,8 @@ export const systemPrompt = (
|
|
18
18
|
|
19
19
|
<tool_selection_guidelines>
|
20
20
|
- For general information queries: Use searchWithSearXNG with the most relevant search engines
|
21
|
-
- For detailed understanding of specific single page content: Use 'crawlSinglePage' on the most authoritative or relevant page from search results. If you need to visit multiple pages, prefer to use 'crawlMultiPages'
|
22
21
|
- For multi-perspective information or comparative analysis: Use 'crawlMultiPages' on several different relevant sources
|
22
|
+
- For detailed understanding of specific single page content: Use 'crawlSinglePage' on the most authoritative or relevant page from search results. If you need to visit multiple pages, prefer to use 'crawlMultiPages'
|
23
23
|
</tool_selection_guidelines>
|
24
24
|
|
25
25
|
<search_categories_selection>
|
@@ -61,7 +61,7 @@ Choose time range based on the query type:
|
|
61
61
|
- Leverage cross-platform meta-search capabilities for comprehensive results
|
62
62
|
- Prioritize authoritative sources in search results when available
|
63
63
|
- For region-specific information, prefer search engines popular in that region
|
64
|
-
- Avoid using both 'engines' and 'categories' in a query, unless the chosen engines do not fall under the selected categories.
|
64
|
+
- Avoid using both 'engines' and 'categories' in a query, unless the chosen engines do not fall under the selected categories.
|
65
65
|
|
66
66
|
<search_strategy_best_practices>
|
67
67
|
- Combine categories for multi-faceted queries:
|
@@ -96,6 +96,20 @@ Choose time range based on the query type:
|
|
96
96
|
- List all referenced URLs at the end of your response
|
97
97
|
- Clearly distinguish between quoted information and your own analysis
|
98
98
|
- Respond in the same language as the user's query
|
99
|
+
|
100
|
+
<citation_examples>
|
101
|
+
<example>
|
102
|
+
According to recent studies, global temperatures have risen by 1.1°C since pre-industrial times[^1].
|
103
|
+
|
104
|
+
[^1]: [Climate Report in 2023](https://example.org/climate-report-2023)
|
105
|
+
</example>
|
106
|
+
<example>
|
107
|
+
以上信息主要基于业内测评和公开发布会(例如2025年4月16日的发布内容)的报道,详细介绍了 O3 与 O4-mini 模型在多模态推理、工具使用、模拟推理和成本效益等方面的综合提升。[^1][^2]
|
108
|
+
|
109
|
+
[^1]: [OpenAI发布o3与o4-mini,性能爆表,可用图像思考](https://zhuanlan.zhihu.com/p/1896105931709849860)
|
110
|
+
[^2]: [OpenAI发新模型o3和o4-mini!首次实现“图像思维”(华尔街见闻)](https://wallstreetcn.com/articles/3745356)
|
111
|
+
</example>
|
112
|
+
</citation_examples>
|
99
113
|
</citation_requirements>
|
100
114
|
|
101
115
|
<response_format>
|
@@ -106,15 +120,10 @@ When providing information from web searches:
|
|
106
120
|
4. List all sources at the end of your response
|
107
121
|
5. For time-sensitive information, note when the information was retrieved
|
108
122
|
|
109
|
-
Example:
|
110
|
-
|
111
|
-
According to recent studies, global temperatures have risen by 1.1°C since pre-industrial times[^1].
|
112
|
-
|
113
|
-
[^1]: [Climate Report in 2023](https://example.org/climate-report-2023)
|
114
123
|
</response_format>
|
115
124
|
|
116
|
-
<
|
117
|
-
|
125
|
+
<search_service_description>
|
126
|
+
Our search service is a metasearch engine that can leverage multiple search engines including:
|
118
127
|
- Google: World's most popular search engine providing broad web results
|
119
128
|
- Bilibili: Chinese video sharing website focused on animation, comics, and games (aka B-site)
|
120
129
|
- Bing: Microsoft's search engine providing web results with emphasis on visual search
|
@@ -135,7 +144,7 @@ SearXNG is a metasearch engine that can leverage multiple search engines includi
|
|
135
144
|
- YouTube: Video sharing platform for searching various video content
|
136
145
|
|
137
146
|
<search_syntax>
|
138
|
-
|
147
|
+
Search service has special search syntax to modify the categories, engines, and language of searches:
|
139
148
|
|
140
149
|
1. Use \`!\` to select engines and categories:
|
141
150
|
- Search for "paris" in the "map" category: \`!map paris\`
|
@@ -148,7 +157,7 @@ SearXNG is a metasearch engine that can leverage multiple search engines includi
|
|
148
157
|
3. Use \`site:\` to restrict results to a specific website:
|
149
158
|
- Search SearXNG from a specific website: \`site:github.com SearXNG\`
|
150
159
|
</search_syntax>
|
151
|
-
</
|
160
|
+
</search_service_description>
|
152
161
|
|
153
162
|
<crawling_best_practices>
|
154
163
|
- Only crawl pages that are publicly accessible
|
@@ -0,0 +1,44 @@
|
|
1
|
+
export interface SearchParams {
|
2
|
+
searchCategories?: string[];
|
3
|
+
searchEngines?: string[];
|
4
|
+
searchTimeRange?: string;
|
5
|
+
}
|
6
|
+
|
7
|
+
export interface SearchQuery extends SearchParams {
|
8
|
+
query: string;
|
9
|
+
}
|
10
|
+
|
11
|
+
export const SEARCH_SEARXNG_NOT_CONFIG = 'SearXNG is not configured';
|
12
|
+
|
13
|
+
export interface SearchContent {
|
14
|
+
content?: string;
|
15
|
+
img_src?: string;
|
16
|
+
publishedDate?: string | null;
|
17
|
+
thumbnail?: string | null;
|
18
|
+
title: string;
|
19
|
+
url: string;
|
20
|
+
}
|
21
|
+
|
22
|
+
export interface UniformSearchResult {
|
23
|
+
category?: string;
|
24
|
+
content: string;
|
25
|
+
engines: string[];
|
26
|
+
/**
|
27
|
+
* 视频会用到
|
28
|
+
*/
|
29
|
+
iframeSrc?: string;
|
30
|
+
imgSrc?: string;
|
31
|
+
parsedUrl: string;
|
32
|
+
publishedDate?: string;
|
33
|
+
score: number;
|
34
|
+
thumbnail?: string;
|
35
|
+
title: string;
|
36
|
+
url: string;
|
37
|
+
}
|
38
|
+
|
39
|
+
export interface UniformSearchResponse {
|
40
|
+
costTime: number;
|
41
|
+
query: string;
|
42
|
+
resultNumbers: number;
|
43
|
+
results: UniformSearchResult[];
|
44
|
+
}
|
@@ -1,48 +0,0 @@
|
|
1
|
-
// @vitest-environment node
|
2
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
3
|
-
|
4
|
-
import { toolsEnv } from '@/config/tools';
|
5
|
-
import { isServerMode } from '@/const/version';
|
6
|
-
/**
|
7
|
-
* This file contains the root router of your tRPC-backend
|
8
|
-
*/
|
9
|
-
import { createCallerFactory } from '@/libs/trpc/lambda';
|
10
|
-
import { AuthContext, createContextInner } from '@/libs/trpc/lambda/context';
|
11
|
-
import { SearXNGClient } from '@/server/modules/SearXNG';
|
12
|
-
|
13
|
-
import { searchRouter } from '../search';
|
14
|
-
import { hetongxue } from './fixtures/searXNG';
|
15
|
-
|
16
|
-
vi.mock('@/config/tools', () => ({
|
17
|
-
toolsEnv: {
|
18
|
-
SEARXNG_URL: 'https://demo.com',
|
19
|
-
},
|
20
|
-
}));
|
21
|
-
|
22
|
-
vi.mock('@/const/version', () => ({
|
23
|
-
isServerMode: true,
|
24
|
-
isDesktop: false,
|
25
|
-
}));
|
26
|
-
|
27
|
-
const createCaller = createCallerFactory(searchRouter);
|
28
|
-
let ctx: AuthContext;
|
29
|
-
let router: ReturnType<typeof createCaller>;
|
30
|
-
|
31
|
-
beforeEach(async () => {
|
32
|
-
vi.resetAllMocks();
|
33
|
-
ctx = await createContextInner({ userId: 'mock' });
|
34
|
-
router = createCaller(ctx);
|
35
|
-
});
|
36
|
-
|
37
|
-
describe('searchRouter', () => {
|
38
|
-
describe('search', () => {
|
39
|
-
it('搜索结果超过10个', async () => {
|
40
|
-
vi.spyOn(SearXNGClient.prototype, 'search').mockResolvedValueOnce(hetongxue);
|
41
|
-
|
42
|
-
const results = await router.query({ query: '何同学' });
|
43
|
-
|
44
|
-
// Assert
|
45
|
-
expect(results.results.length).toEqual(43);
|
46
|
-
});
|
47
|
-
});
|
48
|
-
});
|
package/src/types/tool/search.ts
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
export interface SearchQuery {
|
2
|
-
optionalParams?: {
|
3
|
-
searchCategories?: string[];
|
4
|
-
searchEngines?: string[];
|
5
|
-
searchTimeRange?: string;
|
6
|
-
};
|
7
|
-
query: string;
|
8
|
-
}
|
9
|
-
|
10
|
-
export const SEARCH_SEARXNG_NOT_CONFIG = 'SearXNG is not configured';
|
11
|
-
|
12
|
-
export interface SearchResponse {
|
13
|
-
answers: any[];
|
14
|
-
corrections: any[];
|
15
|
-
infoboxes: any[];
|
16
|
-
number_of_results: number;
|
17
|
-
query: string;
|
18
|
-
results: SearchResult[];
|
19
|
-
suggestions: string[];
|
20
|
-
unresponsive_engines: any[];
|
21
|
-
}
|
22
|
-
|
23
|
-
export interface SearchResult {
|
24
|
-
category: string;
|
25
|
-
content?: string;
|
26
|
-
engine: string;
|
27
|
-
engines: string[];
|
28
|
-
iframe_src?: string;
|
29
|
-
img_src?: string;
|
30
|
-
parsed_url: string[];
|
31
|
-
positions: number[];
|
32
|
-
publishedDate?: string | null;
|
33
|
-
score: number;
|
34
|
-
template: string;
|
35
|
-
thumbnail?: string | null;
|
36
|
-
thumbnail_src?: string | null;
|
37
|
-
title: string;
|
38
|
-
url: string;
|
39
|
-
}
|
40
|
-
|
41
|
-
export interface SearchContent {
|
42
|
-
content?: string;
|
43
|
-
img_src?: string;
|
44
|
-
publishedDate?: string | null;
|
45
|
-
thumbnail?: string | null;
|
46
|
-
title: string;
|
47
|
-
url: string;
|
48
|
-
}
|