@lobehub/chat 1.77.17 → 1.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/changelog/v1.json +18 -0
- package/contributing/Basic/Architecture.md +1 -1
- package/contributing/Basic/Architecture.zh-CN.md +1 -1
- package/contributing/Basic/Chat-API.md +326 -108
- package/contributing/Basic/Chat-API.zh-CN.md +313 -133
- package/contributing/Basic/Contributing-Guidelines.md +7 -4
- package/contributing/Basic/Contributing-Guidelines.zh-CN.md +7 -6
- package/contributing/Home.md +5 -5
- package/contributing/State-Management/State-Management-Intro.md +1 -1
- package/contributing/State-Management/State-Management-Intro.zh-CN.md +1 -1
- package/docs/self-hosting/advanced/auth/next-auth/keycloak.mdx +119 -0
- package/docs/self-hosting/advanced/auth/next-auth/keycloak.zh-CN.mdx +116 -0
- package/docs/self-hosting/advanced/auth.mdx +3 -0
- package/docs/self-hosting/advanced/auth.zh-CN.mdx +3 -0
- package/locales/ar/tool.json +21 -1
- package/locales/bg-BG/tool.json +21 -1
- package/locales/de-DE/tool.json +21 -1
- package/locales/en-US/tool.json +21 -1
- package/locales/es-ES/tool.json +21 -1
- package/locales/fa-IR/tool.json +21 -1
- package/locales/fr-FR/tool.json +21 -1
- package/locales/it-IT/tool.json +21 -1
- package/locales/ja-JP/tool.json +21 -1
- package/locales/ko-KR/tool.json +21 -1
- package/locales/nl-NL/tool.json +21 -1
- package/locales/pl-PL/tool.json +21 -1
- package/locales/pt-BR/tool.json +21 -1
- package/locales/ru-RU/tool.json +21 -1
- package/locales/tr-TR/tool.json +21 -1
- package/locales/vi-VN/tool.json +21 -1
- package/locales/zh-CN/tool.json +30 -1
- package/locales/zh-TW/tool.json +21 -1
- package/package.json +1 -1
- package/src/libs/next-auth/sso-providers/index.ts +2 -0
- package/src/libs/next-auth/sso-providers/keycloak.ts +25 -0
- package/src/locales/default/tool.ts +30 -1
- package/src/server/modules/SearXNG.ts +10 -2
- package/src/server/routers/tools/__test__/search.test.ts +3 -1
- package/src/server/routers/tools/search.ts +10 -2
- package/src/services/search.ts +2 -2
- package/src/store/chat/slices/builtinTool/actions/searXNG.test.ts +28 -8
- package/src/store/chat/slices/builtinTool/actions/searXNG.ts +22 -5
- package/src/tools/web-browsing/Portal/Search/index.tsx +1 -1
- package/src/tools/web-browsing/Render/Search/SearchQuery/SearchView.tsx +1 -1
- package/src/tools/web-browsing/Render/Search/SearchQuery/index.tsx +1 -1
- package/src/tools/web-browsing/Render/Search/SearchResult/index.tsx +1 -1
- package/src/tools/web-browsing/components/CategoryAvatar.tsx +27 -0
- package/src/tools/web-browsing/components/SearchBar.tsx +84 -4
- package/src/tools/web-browsing/const.ts +26 -0
- package/src/tools/web-browsing/index.ts +58 -28
- package/src/tools/web-browsing/systemRole.ts +62 -1
- package/src/types/tool/search.ts +10 -1
- package/src/helpers/url.ts +0 -17
package/locales/pt-BR/tool.json
CHANGED
@@ -19,8 +19,28 @@
|
|
19
19
|
"placeholder": "Palavras-chave",
|
20
20
|
"tooltip": "Isso irá recuperar os resultados da pesquisa novamente e criar uma nova mensagem de resumo"
|
21
21
|
},
|
22
|
-
"
|
22
|
+
"searchCategory": {
|
23
|
+
"placeholder": "Pesquisar categoria",
|
24
|
+
"title": "Categoria de pesquisa:",
|
25
|
+
"value": {
|
26
|
+
"files": "Arquivos",
|
27
|
+
"general": "Geral",
|
28
|
+
"images": "Imagens",
|
29
|
+
"it": "Tecnologia da Informação",
|
30
|
+
"map": "Mapa",
|
31
|
+
"music": "Música",
|
32
|
+
"news": "Notícias",
|
33
|
+
"science": "Ciência",
|
34
|
+
"social_media": "Mídias sociais",
|
35
|
+
"videos": "Vídeos"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"searchEngine": {
|
39
|
+
"placeholder": "Motor de busca",
|
40
|
+
"title": "Motor de busca:"
|
41
|
+
},
|
23
42
|
"searchResult": "Número de pesquisas:",
|
43
|
+
"searchTimeRange": "Intervalo de tempo:",
|
24
44
|
"summary": "Resumo",
|
25
45
|
"summaryTooltip": "Resumir o conteúdo atual",
|
26
46
|
"viewMoreResults": "Ver mais {{results}} resultados"
|
package/locales/ru-RU/tool.json
CHANGED
@@ -19,8 +19,28 @@
|
|
19
19
|
"placeholder": "Ключевые слова",
|
20
20
|
"tooltip": "Будет повторно получен результат поиска и создано новое резюме сообщения"
|
21
21
|
},
|
22
|
-
"
|
22
|
+
"searchCategory": {
|
23
|
+
"placeholder": "Поиск категории",
|
24
|
+
"title": "Категория поиска:",
|
25
|
+
"value": {
|
26
|
+
"files": "Файлы",
|
27
|
+
"general": "Общее",
|
28
|
+
"images": "Изображения",
|
29
|
+
"it": "Информационные технологии",
|
30
|
+
"map": "Карта",
|
31
|
+
"music": "Музыка",
|
32
|
+
"news": "Новости",
|
33
|
+
"science": "Наука",
|
34
|
+
"social_media": "Социальные медиа",
|
35
|
+
"videos": "Видео"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"searchEngine": {
|
39
|
+
"placeholder": "Поисковая система",
|
40
|
+
"title": "Поисковая система:"
|
41
|
+
},
|
23
42
|
"searchResult": "Количество результатов:",
|
43
|
+
"searchTimeRange": "Временной диапазон:",
|
24
44
|
"summary": "Резюме",
|
25
45
|
"summaryTooltip": "Суммировать текущее содержимое",
|
26
46
|
"viewMoreResults": "Посмотреть еще {{results}} результатов"
|
package/locales/tr-TR/tool.json
CHANGED
@@ -19,8 +19,28 @@
|
|
19
19
|
"placeholder": "Anahtar kelime",
|
20
20
|
"tooltip": "Arama sonuçları yeniden alınacak ve yeni bir özet mesajı oluşturulacaktır"
|
21
21
|
},
|
22
|
-
"
|
22
|
+
"searchCategory": {
|
23
|
+
"placeholder": "Kategori Ara",
|
24
|
+
"title": "Kategori Ara:",
|
25
|
+
"value": {
|
26
|
+
"files": "Dosyalar",
|
27
|
+
"general": "Genel",
|
28
|
+
"images": "Görüntüler",
|
29
|
+
"it": "Bilgi Teknolojisi",
|
30
|
+
"map": "Harita",
|
31
|
+
"music": "Müzik",
|
32
|
+
"news": "Haberler",
|
33
|
+
"science": "Bilim",
|
34
|
+
"social_media": "Sosyal Medya",
|
35
|
+
"videos": "Videolar"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"searchEngine": {
|
39
|
+
"placeholder": "Arama Motoru",
|
40
|
+
"title": "Arama Motoru:"
|
41
|
+
},
|
23
42
|
"searchResult": "Arama sayısı:",
|
43
|
+
"searchTimeRange": "Zaman aralığı:",
|
24
44
|
"summary": "Özet",
|
25
45
|
"summaryTooltip": "Mevcut içeriği özetle",
|
26
46
|
"viewMoreResults": "Daha fazla {{results}} sonuç görüntüle"
|
package/locales/vi-VN/tool.json
CHANGED
@@ -19,8 +19,28 @@
|
|
19
19
|
"placeholder": "Từ khóa",
|
20
20
|
"tooltip": "Sẽ lấy lại kết quả tìm kiếm và tạo một tin nhắn tóm tắt mới"
|
21
21
|
},
|
22
|
-
"
|
22
|
+
"searchCategory": {
|
23
|
+
"placeholder": "Tìm kiếm danh mục",
|
24
|
+
"title": "Danh mục tìm kiếm:",
|
25
|
+
"value": {
|
26
|
+
"files": "Tài liệu",
|
27
|
+
"general": "Chung",
|
28
|
+
"images": "Hình ảnh",
|
29
|
+
"it": "Công nghệ thông tin",
|
30
|
+
"map": "Bản đồ",
|
31
|
+
"music": "Âm nhạc",
|
32
|
+
"news": "Tin tức",
|
33
|
+
"science": "Khoa học",
|
34
|
+
"social_media": "Mạng xã hội",
|
35
|
+
"videos": "Video"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"searchEngine": {
|
39
|
+
"placeholder": "Công cụ tìm kiếm",
|
40
|
+
"title": "Công cụ tìm kiếm:"
|
41
|
+
},
|
23
42
|
"searchResult": "Số lượng tìm kiếm:",
|
43
|
+
"searchTimeRange": "Khoảng thời gian:",
|
24
44
|
"summary": "Tóm tắt",
|
25
45
|
"summaryTooltip": "Tóm tắt nội dung hiện tại",
|
26
46
|
"viewMoreResults": "Xem thêm {{results}} kết quả"
|
package/locales/zh-CN/tool.json
CHANGED
@@ -19,8 +19,37 @@
|
|
19
19
|
"placeholder": "关键词",
|
20
20
|
"tooltip": "将会重新获取搜索结果,并创建一条新的总结消息"
|
21
21
|
},
|
22
|
-
"
|
22
|
+
"searchCategory": {
|
23
|
+
"placeholder": "搜索类别",
|
24
|
+
"title": "搜索类别:",
|
25
|
+
"value": {
|
26
|
+
"files": "文件",
|
27
|
+
"general": "通用",
|
28
|
+
"images": "图片",
|
29
|
+
"it": "信息技术",
|
30
|
+
"map": "地图",
|
31
|
+
"music": "音乐",
|
32
|
+
"news": "新闻",
|
33
|
+
"science": "科学",
|
34
|
+
"social_media": "社交媒体",
|
35
|
+
"videos": "视频"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"searchEngine": {
|
39
|
+
"placeholder": "搜索引擎",
|
40
|
+
"title": "搜索引擎:"
|
41
|
+
},
|
23
42
|
"searchResult": "搜索数量:",
|
43
|
+
"searchTimeRange": {
|
44
|
+
"title": "时间范围:",
|
45
|
+
"value": {
|
46
|
+
"anytime": "时间不限",
|
47
|
+
"day": "一天内",
|
48
|
+
"month": "一月内",
|
49
|
+
"week": "一周内",
|
50
|
+
"year": "一年内"
|
51
|
+
}
|
52
|
+
},
|
24
53
|
"summary": "总结",
|
25
54
|
"summaryTooltip": "总结当前内容",
|
26
55
|
"viewMoreResults": "查看更多 {{results}} 个结果"
|
package/locales/zh-TW/tool.json
CHANGED
@@ -19,8 +19,28 @@
|
|
19
19
|
"placeholder": "關鍵字",
|
20
20
|
"tooltip": "將會重新獲取搜尋結果,並建立一條新的總結消息"
|
21
21
|
},
|
22
|
-
"
|
22
|
+
"searchCategory": {
|
23
|
+
"placeholder": "搜尋類別",
|
24
|
+
"title": "搜尋類別:",
|
25
|
+
"value": {
|
26
|
+
"files": "文件",
|
27
|
+
"general": "通用",
|
28
|
+
"images": "圖片",
|
29
|
+
"it": "資訊科技",
|
30
|
+
"map": "地圖",
|
31
|
+
"music": "音樂",
|
32
|
+
"news": "新聞",
|
33
|
+
"science": "科學",
|
34
|
+
"social_media": "社交媒體",
|
35
|
+
"videos": "影片"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"searchEngine": {
|
39
|
+
"placeholder": "搜尋引擎",
|
40
|
+
"title": "搜尋引擎:"
|
41
|
+
},
|
23
42
|
"searchResult": "搜尋數量:",
|
43
|
+
"searchTimeRange": "時間範圍:",
|
24
44
|
"summary": "總結",
|
25
45
|
"summaryTooltip": "總結當前內容",
|
26
46
|
"viewMoreResults": "查看更多 {{results}} 個結果"
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.78.0",
|
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",
|
@@ -6,6 +6,7 @@ import Casdoor from './casdoor';
|
|
6
6
|
import CloudflareZeroTrust from './cloudflare-zero-trust';
|
7
7
|
import GenericOIDC from './generic-oidc';
|
8
8
|
import Github from './github';
|
9
|
+
import Keycloak from './keycloak';
|
9
10
|
import Logto from './logto';
|
10
11
|
import MicrosoftEntraID from './microsoft-entra-id';
|
11
12
|
import WeChat from './wechat';
|
@@ -24,4 +25,5 @@ export const ssoProviders = [
|
|
24
25
|
Casdoor,
|
25
26
|
MicrosoftEntraID,
|
26
27
|
WeChat,
|
28
|
+
Keycloak,
|
27
29
|
];
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import Keycloak from 'next-auth/providers/keycloak';
|
2
|
+
|
3
|
+
import { CommonProviderConfig } from './sso.config';
|
4
|
+
|
5
|
+
const provider = {
|
6
|
+
id: 'keycloak',
|
7
|
+
provider: Keycloak({
|
8
|
+
...CommonProviderConfig,
|
9
|
+
// Specify auth scope, at least include 'openid email'
|
10
|
+
authorization: { params: { scope: 'openid email profile' } },
|
11
|
+
clientId: process.env.AUTH_KEYCLOAK_ID,
|
12
|
+
clientSecret: process.env.AUTH_KEYCLOAK_SECRET,
|
13
|
+
issuer: process.env.AUTH_KEYCLOAK_ISSUER,
|
14
|
+
profile(profile) {
|
15
|
+
return {
|
16
|
+
email: profile.email,
|
17
|
+
id: profile.sub,
|
18
|
+
name: profile.name,
|
19
|
+
providerAccountId: profile.sub,
|
20
|
+
};
|
21
|
+
},
|
22
|
+
}),
|
23
|
+
};
|
24
|
+
|
25
|
+
export default provider;
|
@@ -19,8 +19,37 @@ export default {
|
|
19
19
|
placeholder: '关键词',
|
20
20
|
tooltip: '将会重新获取搜索结果,并创建一条新的总结消息',
|
21
21
|
},
|
22
|
-
|
22
|
+
searchCategory: {
|
23
|
+
placeholder: '搜索类别',
|
24
|
+
title: '搜索类别:',
|
25
|
+
value: {
|
26
|
+
'files': '文件',
|
27
|
+
'general': '通用',
|
28
|
+
'images': '图片',
|
29
|
+
'it': '信息技术',
|
30
|
+
'map': '地图',
|
31
|
+
'music': '音乐',
|
32
|
+
'news': '新闻',
|
33
|
+
'science': '科学',
|
34
|
+
'social_media': '社交媒体',
|
35
|
+
'videos': '视频',
|
36
|
+
},
|
37
|
+
},
|
38
|
+
searchEngine: {
|
39
|
+
placeholder: '搜索引擎',
|
40
|
+
title: '搜索引擎:',
|
41
|
+
},
|
23
42
|
searchResult: '搜索数量:',
|
43
|
+
searchTimeRange: {
|
44
|
+
title: '时间范围:',
|
45
|
+
value: {
|
46
|
+
anytime: '时间不限',
|
47
|
+
day: '一天内',
|
48
|
+
month: '一月内',
|
49
|
+
week: '一周内',
|
50
|
+
year: '一年内',
|
51
|
+
},
|
52
|
+
},
|
24
53
|
summary: '总结',
|
25
54
|
summaryTooltip: '总结当前内容',
|
26
55
|
viewMoreResults: '查看更多 {{results}} 个结果',
|
@@ -10,10 +10,18 @@ export class SearXNGClient {
|
|
10
10
|
this.baseUrl = baseUrl;
|
11
11
|
}
|
12
12
|
|
13
|
-
async search(query: string,
|
13
|
+
async search(query: string, optionalParams: Record<string, any> = {}): Promise<SearchResponse> {
|
14
14
|
try {
|
15
|
+
const { time_range, ...otherParams } = optionalParams;
|
16
|
+
|
17
|
+
const processedParams = Object.entries(otherParams).reduce<Record<string, any>>((acc, [key, value]) => {
|
18
|
+
acc[key] = Array.isArray(value) ? value.join(',') : value;
|
19
|
+
return acc;
|
20
|
+
}, {});
|
21
|
+
|
15
22
|
const searchParams = qs.stringify({
|
16
|
-
|
23
|
+
...processedParams,
|
24
|
+
...(time_range !== 'anytime' && { time_range }),
|
17
25
|
format: 'json',
|
18
26
|
q: query,
|
19
27
|
});
|
@@ -98,8 +98,10 @@ describe('searchRouter', () => {
|
|
98
98
|
const caller = searchRouter.createCaller(mockContext as any);
|
99
99
|
|
100
100
|
const result = await caller.query({
|
101
|
+
optionalParams: {
|
102
|
+
searchEngines: ['google'],
|
103
|
+
},
|
101
104
|
query: 'test query',
|
102
|
-
searchEngine: ['google'],
|
103
105
|
});
|
104
106
|
|
105
107
|
expect(result).toEqual(mockSearchResult);
|
@@ -43,8 +43,12 @@ export const searchRouter = router({
|
|
43
43
|
query: searchProcedure
|
44
44
|
.input(
|
45
45
|
z.object({
|
46
|
+
optionalParams: z.object({
|
47
|
+
searchCategories: z.array(z.string()).optional(),
|
48
|
+
searchEngines: z.array(z.string()).optional(),
|
49
|
+
searchTimeRange: z.string().optional(),
|
50
|
+
}).optional(),
|
46
51
|
query: z.string(),
|
47
|
-
searchEngine: z.array(z.string()).optional(),
|
48
52
|
}),
|
49
53
|
)
|
50
54
|
.query(async ({ input }) => {
|
@@ -55,7 +59,11 @@ export const searchRouter = router({
|
|
55
59
|
const client = new SearXNGClient(toolsEnv.SEARXNG_URL);
|
56
60
|
|
57
61
|
try {
|
58
|
-
return await client.search(input.query,
|
62
|
+
return await client.search(input.query, {
|
63
|
+
categories: input.optionalParams?.searchCategories,
|
64
|
+
engines: input.optionalParams?.searchEngines,
|
65
|
+
time_range: input.optionalParams?.searchTimeRange,
|
66
|
+
});
|
59
67
|
} catch (e) {
|
60
68
|
console.error(e);
|
61
69
|
|
package/src/services/search.ts
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
import { toolsClient } from '@/libs/trpc/client';
|
2
2
|
|
3
3
|
class SearchService {
|
4
|
-
search(query: string,
|
5
|
-
return toolsClient.search.query.query({
|
4
|
+
search(query: string, optionalParams?: object) {
|
5
|
+
return toolsClient.search.query.query({ optionalParams, query});
|
6
6
|
}
|
7
7
|
|
8
8
|
crawlPage(url: string) {
|
@@ -72,8 +72,10 @@ describe('searXNG actions', () => {
|
|
72
72
|
|
73
73
|
const messageId = 'test-message-id';
|
74
74
|
const query: SearchQuery = {
|
75
|
+
optionalParams: {
|
76
|
+
searchEngines: ['google'],
|
77
|
+
},
|
75
78
|
query: 'test query',
|
76
|
-
searchEngines: ['google'],
|
77
79
|
};
|
78
80
|
|
79
81
|
await act(async () => {
|
@@ -82,13 +84,15 @@ describe('searXNG actions', () => {
|
|
82
84
|
|
83
85
|
const expectedContent: SearchContent[] = [
|
84
86
|
{
|
85
|
-
content: 'Test Content',
|
86
87
|
title: 'Test Result',
|
87
88
|
url: 'https://test.com',
|
89
|
+
content: 'Test Content',
|
88
90
|
},
|
89
91
|
];
|
90
92
|
|
91
|
-
expect(searchService.search).toHaveBeenCalledWith('test query',
|
93
|
+
expect( searchService.search ).toHaveBeenCalledWith('test query', {
|
94
|
+
searchEngines: [ 'google' ]
|
95
|
+
});
|
92
96
|
expect(result.current.searchLoading[messageId]).toBe(false);
|
93
97
|
expect(result.current.internal_updateMessageContent).toHaveBeenCalledWith(
|
94
98
|
messageId,
|
@@ -133,6 +137,7 @@ describe('searXNG actions', () => {
|
|
133
137
|
};
|
134
138
|
|
135
139
|
(searchService.search as Mock)
|
140
|
+
.mockResolvedValueOnce(emptyResponse)
|
136
141
|
.mockResolvedValueOnce(emptyResponse)
|
137
142
|
.mockResolvedValueOnce(retryResponse);
|
138
143
|
|
@@ -141,20 +146,35 @@ describe('searXNG actions', () => {
|
|
141
146
|
|
142
147
|
const messageId = 'test-message-id';
|
143
148
|
const query: SearchQuery = {
|
149
|
+
optionalParams: {
|
150
|
+
searchEngines: ['custom-engine'],
|
151
|
+
searchTimeRange: 'year',
|
152
|
+
},
|
144
153
|
query: 'test query',
|
145
|
-
searchEngines: ['custom-engine'],
|
146
154
|
};
|
147
155
|
|
148
156
|
await act(async () => {
|
149
157
|
await searchWithSearXNG(messageId, query);
|
150
158
|
});
|
151
159
|
|
152
|
-
expect(searchService.search).toHaveBeenCalledTimes(
|
153
|
-
expect(searchService.search).toHaveBeenNthCalledWith(1,
|
154
|
-
|
160
|
+
expect(searchService.search).toHaveBeenCalledTimes(3);
|
161
|
+
expect(searchService.search).toHaveBeenNthCalledWith(1, "test query", {
|
162
|
+
"searchEngines": [ "custom-engine" ],
|
163
|
+
"searchTimeRange": "year",
|
164
|
+
});
|
165
|
+
expect(searchService.search).toHaveBeenNthCalledWith(2, "test query", {
|
166
|
+
"searchTimeRange": "year",
|
167
|
+
});
|
168
|
+
expect(result.current.updatePluginArguments).toHaveBeenCalledWith(messageId, {
|
169
|
+
optionalParams: {
|
170
|
+
"searchTimeRange": "year",
|
171
|
+
},
|
172
|
+
query: 'test query',
|
173
|
+
});
|
174
|
+
expect(searchService.search).toHaveBeenNthCalledWith(3, "test query");
|
155
175
|
expect(result.current.updatePluginArguments).toHaveBeenCalledWith(messageId, {
|
176
|
+
optionalParams: undefined,
|
156
177
|
query: 'test query',
|
157
|
-
searchEngines: undefined,
|
158
178
|
});
|
159
179
|
});
|
160
180
|
|
@@ -142,12 +142,26 @@ export const searchSlice: StateCreator<
|
|
142
142
|
get().toggleSearchLoading(id, true);
|
143
143
|
let data: SearchResponse | undefined;
|
144
144
|
try {
|
145
|
-
|
145
|
+
// 首次查询
|
146
|
+
data = await searchService.search(params.query, params.optionalParams);
|
147
|
+
|
148
|
+
// 如果没有搜索到结果,则执行第一次重试(移除搜索引擎限制)
|
149
|
+
if (data?.results.length === 0 && params.optionalParams?.searchEngines && params.optionalParams?.searchEngines?.length > 0) {
|
150
|
+
const paramsExcludeSearchEngines = {
|
151
|
+
...params,
|
152
|
+
optionalParams: {
|
153
|
+
...params.optionalParams,
|
154
|
+
searchEngines: undefined
|
155
|
+
}
|
156
|
+
};
|
157
|
+
data = await searchService.search(params.query, paramsExcludeSearchEngines.optionalParams);
|
158
|
+
get().updatePluginArguments(id, paramsExcludeSearchEngines);
|
159
|
+
}
|
146
160
|
|
147
|
-
//
|
148
|
-
if (data?.results.length === 0
|
161
|
+
// 如果仍然没有搜索到结果,则执行第二次重试(移除所有限制)
|
162
|
+
if (data?.results.length === 0) {
|
149
163
|
data = await searchService.search(params.query);
|
150
|
-
get().updatePluginArguments(id, { ...params,
|
164
|
+
get().updatePluginArguments(id, { ...params, optionalParams: undefined });
|
151
165
|
}
|
152
166
|
|
153
167
|
await get().updatePluginState(id, data);
|
@@ -175,9 +189,12 @@ export const searchSlice: StateCreator<
|
|
175
189
|
|
176
190
|
// add 15 search results to message content
|
177
191
|
const searchContent: SearchContent[] = data.results.slice(0, 15).map((item) => ({
|
178
|
-
content: item.content,
|
179
192
|
title: item.title,
|
180
193
|
url: item.url,
|
194
|
+
...(item.content && { content: item.content }),
|
195
|
+
...(item.publishedDate && { publishedDate: item.publishedDate }),
|
196
|
+
...(item.img_src && { img_src: item.img_src }),
|
197
|
+
...(item.thumbnail && { thumbnail: item.thumbnail }),
|
181
198
|
}));
|
182
199
|
|
183
200
|
await get().internal_updateMessageContent(id, JSON.stringify(searchContent));
|
@@ -19,7 +19,7 @@ interface InspectorUIProps {
|
|
19
19
|
|
20
20
|
const Inspector = memo<InspectorUIProps>(({ query: args, messageId, response }) => {
|
21
21
|
const engines = uniq((response.results || []).map((result) => result.engine));
|
22
|
-
const defaultEngines = engines.length > 0 ? engines : args.searchEngines || [];
|
22
|
+
const defaultEngines = engines.length > 0 ? engines : args.optionalParams?.searchEngines || [];
|
23
23
|
const loading = useChatStore(chatToolSelectors.isSearXNGSearching(messageId));
|
24
24
|
|
25
25
|
if (loading) {
|
@@ -66,7 +66,7 @@ const SearchBar = memo<SearchBarProps>(
|
|
66
66
|
</Flexbox>
|
67
67
|
|
68
68
|
<Flexbox align={'center'} horizontal>
|
69
|
-
<div className={styles.font}>{t('search.searchEngine')}</div>
|
69
|
+
<div className={styles.font}>{t('search.searchEngine.title')}</div>
|
70
70
|
{searching ? (
|
71
71
|
<Skeleton.Button active size={'small'} />
|
72
72
|
) : (
|
@@ -29,7 +29,7 @@ const SearchQueryView = memo<SearchQueryViewProps>(
|
|
29
29
|
const { t } = useTranslation('common');
|
30
30
|
|
31
31
|
const engines = uniq(searchResults.map((result) => result.engine));
|
32
|
-
const defaultEngines = engines.length > 0 ? engines : args.searchEngines || [];
|
32
|
+
const defaultEngines = engines.length > 0 ? engines : args.optionalParams?.searchEngines || [];
|
33
33
|
|
34
34
|
return !pluginState ? (
|
35
35
|
<Flexbox align={'center'} distribution={'space-between'} height={32} horizontal>
|
@@ -32,7 +32,7 @@ const SearchResult = memo<SearchResultProps>(
|
|
32
32
|
const { t } = useTranslation(['tool', 'common']);
|
33
33
|
|
34
34
|
const engines = uniq(searchResults.map((result) => result.engine));
|
35
|
-
const defaultEngines = engines.length > 0 ? engines : args.searchEngines || [];
|
35
|
+
const defaultEngines = engines.length > 0 ? engines : args.optionalParams?.searchEngines || [];
|
36
36
|
const isMobile = useIsMobile();
|
37
37
|
|
38
38
|
if (loading || !pluginState)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { Avatar } from 'antd';
|
2
|
+
import { useTheme } from 'antd-style';
|
3
|
+
import { memo } from 'react';
|
4
|
+
|
5
|
+
import { CATEGORY_ICON_MAP } from '../const';
|
6
|
+
|
7
|
+
interface CategoryAvatarProps {
|
8
|
+
category: string;
|
9
|
+
}
|
10
|
+
|
11
|
+
export const CategoryAvatar = memo<CategoryAvatarProps>(({ category }) => {
|
12
|
+
const theme = useTheme();
|
13
|
+
const IconComponent = CATEGORY_ICON_MAP[category];
|
14
|
+
|
15
|
+
return (
|
16
|
+
<Avatar
|
17
|
+
alt={category}
|
18
|
+
icon={<IconComponent />}
|
19
|
+
style={{
|
20
|
+
backgroundColor: 'transparent',
|
21
|
+
color: theme.colorTextSecondary,
|
22
|
+
height: 16,
|
23
|
+
width: 16
|
24
|
+
}}
|
25
|
+
/>
|
26
|
+
);
|
27
|
+
});
|