@lobehub/lobehub 2.0.0-next.4 → 2.0.0-next.5
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 +25 -0
- package/changelog/v1.json +9 -0
- package/docs/development/database-schema.dbml +11 -1
- package/docs/self-hosting/advanced/online-search.mdx +30 -25
- package/docs/self-hosting/advanced/online-search.zh-CN.mdx +25 -23
- package/package.json +1 -1
- package/packages/database/migrations/0041_improve_index.sql +10 -0
- package/packages/database/migrations/meta/0041_snapshot.json +7784 -0
- package/packages/database/migrations/meta/_journal.json +7 -0
- package/packages/database/src/core/migrations.json +17 -0
- package/packages/database/src/models/session.ts +60 -19
- package/packages/database/src/schemas/agent.ts +10 -11
- package/packages/database/src/schemas/message.ts +5 -1
- package/packages/database/src/schemas/relations.ts +6 -4
- package/packages/database/src/schemas/session.ts +2 -0
- package/packages/database/src/schemas/topic.ts +6 -1
- package/packages/model-bank/src/aiModels/anthropic.ts +0 -63
- package/packages/model-bank/src/aiModels/higress.ts +0 -55
- package/packages/model-bank/src/aiModels/infiniai.ts +21 -0
- package/packages/model-bank/src/aiModels/ollamacloud.ts +13 -0
- package/packages/model-bank/src/aiModels/siliconcloud.ts +19 -0
- package/packages/model-runtime/src/core/streams/openai/__snapshots__/responsesStream.test.ts.snap +0 -38
- package/packages/model-runtime/src/providers/minimax/index.ts +5 -5
- package/packages/model-runtime/src/providers/search1api/index.test.ts +2 -2
- package/packages/web-crawler/src/crawImpl/firecrawl.ts +39 -12
- package/scripts/migrateServerDB/index.ts +2 -1
- package/src/config/modelProviders/anthropic.ts +0 -23
- package/src/config/modelProviders/higress.ts +0 -23
- package/src/config/modelProviders/minimax.ts +1 -1
- package/src/config/modelProviders/qiniu.ts +1 -1
- package/src/server/routers/lambda/session.ts +8 -5
- package/src/server/services/search/impls/firecrawl/index.ts +51 -11
- package/src/server/services/search/impls/firecrawl/type.ts +60 -9
- package/src/services/user/client.test.ts +4 -1
|
@@ -48,29 +48,6 @@ const Anthropic: ModelProviderCard = {
|
|
|
48
48
|
maxOutput: 8192,
|
|
49
49
|
releasedAt: '2024-11-05',
|
|
50
50
|
},
|
|
51
|
-
{
|
|
52
|
-
contextWindowTokens: 200_000,
|
|
53
|
-
description:
|
|
54
|
-
'Claude 3.5 Sonnet 提供了超越 Opus 的能力和比 Sonnet 更快的速度,同时保持与 Sonnet 相同的价格。Sonnet 特别擅长编程、数据科学、视觉处理、代理任务。',
|
|
55
|
-
displayName: 'Claude 3.5 Sonnet',
|
|
56
|
-
enabled: true,
|
|
57
|
-
functionCall: true,
|
|
58
|
-
id: 'claude-3-5-sonnet-20241022',
|
|
59
|
-
maxOutput: 8192,
|
|
60
|
-
releasedAt: '2024-10-22',
|
|
61
|
-
vision: true,
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
contextWindowTokens: 200_000,
|
|
65
|
-
description:
|
|
66
|
-
'Claude 3.5 Sonnet 提供了超越 Opus 的能力和比 Sonnet 更快的速度,同时保持与 Sonnet 相同的价格。Sonnet 特别擅长编程、数据科学、视觉处理、代理任务。',
|
|
67
|
-
displayName: 'Claude 3.5 Sonnet 0620',
|
|
68
|
-
functionCall: true,
|
|
69
|
-
id: 'claude-3-5-sonnet-20240620',
|
|
70
|
-
maxOutput: 8192,
|
|
71
|
-
releasedAt: '2024-06-20',
|
|
72
|
-
vision: true,
|
|
73
|
-
},
|
|
74
51
|
{
|
|
75
52
|
contextWindowTokens: 200_000,
|
|
76
53
|
description:
|
|
@@ -1298,29 +1298,6 @@ const Higress: ModelProviderCard = {
|
|
|
1298
1298
|
maxOutput: 8192,
|
|
1299
1299
|
releasedAt: '2024-11-05',
|
|
1300
1300
|
},
|
|
1301
|
-
{
|
|
1302
|
-
contextWindowTokens: 200_000,
|
|
1303
|
-
description:
|
|
1304
|
-
'Claude 3.5 Sonnet 提供了超越 Opus 的能力和比 Sonnet 更快的速度,同时保持与 Sonnet 相同的价格。Sonnet 特别擅长编程、数据科学、视觉处理、代理任务。',
|
|
1305
|
-
displayName: 'Claude 3.5 Sonnet',
|
|
1306
|
-
enabled: true,
|
|
1307
|
-
functionCall: true,
|
|
1308
|
-
id: 'claude-3-5-sonnet-20241022',
|
|
1309
|
-
maxOutput: 8192,
|
|
1310
|
-
releasedAt: '2024-10-22',
|
|
1311
|
-
vision: true,
|
|
1312
|
-
},
|
|
1313
|
-
{
|
|
1314
|
-
contextWindowTokens: 200_000,
|
|
1315
|
-
description:
|
|
1316
|
-
'Claude 3.5 Sonnet 提供了超越 Opus 的能力和比 Sonnet 更快的速度,同时保持与 Sonnet 相同的价格。Sonnet 特别擅长编程、数据科学、视觉处理、代理任务。',
|
|
1317
|
-
displayName: 'Claude 3.5 Sonnet 0620',
|
|
1318
|
-
functionCall: true,
|
|
1319
|
-
id: 'claude-3-5-sonnet-20240620',
|
|
1320
|
-
maxOutput: 8192,
|
|
1321
|
-
releasedAt: '2024-06-20',
|
|
1322
|
-
vision: true,
|
|
1323
|
-
},
|
|
1324
1301
|
{
|
|
1325
1302
|
contextWindowTokens: 200_000,
|
|
1326
1303
|
description:
|
|
@@ -97,14 +97,17 @@ export const sessionRouter = router({
|
|
|
97
97
|
}),
|
|
98
98
|
|
|
99
99
|
getGroupedSessions: publicProcedure.query(async ({ ctx }): Promise<ChatSessionList> => {
|
|
100
|
-
|
|
100
|
+
const userId = ctx.userId;
|
|
101
|
+
if (!userId) return { sessionGroups: [], sessions: [] };
|
|
101
102
|
|
|
102
103
|
const serverDB = await getServerDB();
|
|
103
|
-
const sessionModel = new SessionModel(serverDB,
|
|
104
|
-
const chatGroupModel = new ChatGroupModel(serverDB,
|
|
104
|
+
const sessionModel = new SessionModel(serverDB, userId);
|
|
105
|
+
const chatGroupModel = new ChatGroupModel(serverDB, userId);
|
|
105
106
|
|
|
106
|
-
const { sessions, sessionGroups } = await
|
|
107
|
-
|
|
107
|
+
const [{ sessions, sessionGroups }, chatGroups] = await Promise.all([
|
|
108
|
+
sessionModel.queryWithGroups(),
|
|
109
|
+
chatGroupModel.queryWithMemberDetails(),
|
|
110
|
+
]);
|
|
108
111
|
|
|
109
112
|
const groupSessions: LobeGroupSession[] = chatGroups.map((group) => {
|
|
110
113
|
const { title, description, avatar, backgroundColor, groupId, ...rest } = group;
|
|
@@ -26,7 +26,7 @@ export class FirecrawlImpl implements SearchServiceImpl {
|
|
|
26
26
|
|
|
27
27
|
private get baseUrl(): string {
|
|
28
28
|
// Assuming the base URL is consistent with the crawl endpoint
|
|
29
|
-
return process.env.FIRECRAWL_URL || 'https://api.firecrawl.dev/
|
|
29
|
+
return process.env.FIRECRAWL_URL || 'https://api.firecrawl.dev/v2';
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
async query(query: string, params: SearchParams = {}): Promise<UniformSearchResponse> {
|
|
@@ -34,13 +34,14 @@ export class FirecrawlImpl implements SearchServiceImpl {
|
|
|
34
34
|
const endpoint = urlJoin(this.baseUrl, '/search');
|
|
35
35
|
|
|
36
36
|
const defaultQueryParams: FirecrawlSearchParameters = {
|
|
37
|
-
limit:
|
|
37
|
+
limit: 20,
|
|
38
38
|
query,
|
|
39
39
|
/*
|
|
40
40
|
scrapeOptions: {
|
|
41
41
|
formats: ["markdown"]
|
|
42
42
|
},
|
|
43
43
|
*/
|
|
44
|
+
sources: [{ type: 'web' }, { type: 'news' }],
|
|
44
45
|
};
|
|
45
46
|
|
|
46
47
|
let body: FirecrawlSearchParameters = {
|
|
@@ -95,25 +96,64 @@ export class FirecrawlImpl implements SearchServiceImpl {
|
|
|
95
96
|
|
|
96
97
|
log('Parsed Firecrawl response: %o', firecrawlResponse);
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
// V2 API returns data as object with web/images/news arrays
|
|
100
|
+
const webResults = firecrawlResponse.data.web || [];
|
|
101
|
+
const imageResults = firecrawlResponse.data.images || [];
|
|
102
|
+
const newsResults = firecrawlResponse.data.news || [];
|
|
103
|
+
|
|
104
|
+
// Map web results
|
|
105
|
+
const mappedWebResults = webResults.map(
|
|
106
|
+
(result): UniformSearchResult => ({
|
|
107
|
+
category: 'general',
|
|
108
|
+
content: result.description || result.markdown || '',
|
|
109
|
+
engines: ['firecrawl'],
|
|
110
|
+
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
111
|
+
score: 1,
|
|
112
|
+
title: result.title || '',
|
|
113
|
+
url: result.url,
|
|
114
|
+
}),
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Map news results
|
|
118
|
+
const mappedNewsResults = newsResults.map(
|
|
99
119
|
(result): UniformSearchResult => ({
|
|
100
|
-
category: '
|
|
101
|
-
content: result.
|
|
102
|
-
engines: ['firecrawl'],
|
|
103
|
-
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
104
|
-
score: 1,
|
|
120
|
+
category: 'news',
|
|
121
|
+
content: result.snippet || result.markdown || '',
|
|
122
|
+
engines: ['firecrawl'],
|
|
123
|
+
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
124
|
+
score: 1,
|
|
105
125
|
title: result.title || '',
|
|
106
126
|
url: result.url,
|
|
107
127
|
}),
|
|
108
128
|
);
|
|
109
129
|
|
|
110
|
-
|
|
130
|
+
// Map image results
|
|
131
|
+
const mappedImageResults = imageResults.map(
|
|
132
|
+
(result): UniformSearchResult => ({
|
|
133
|
+
category: 'images',
|
|
134
|
+
content: result.title || '',
|
|
135
|
+
engines: ['firecrawl'],
|
|
136
|
+
parsedUrl: result.url ? new URL(result.url).hostname : '',
|
|
137
|
+
score: 1,
|
|
138
|
+
title: result.title || '',
|
|
139
|
+
url: result.imageUrl, // Use imageUrl for images
|
|
140
|
+
}),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
// Combine all results
|
|
144
|
+
const allResults = [...mappedWebResults, ...mappedNewsResults, ...mappedImageResults];
|
|
145
|
+
|
|
146
|
+
log('Mapped %d results to SearchResult format', allResults.length);
|
|
147
|
+
|
|
148
|
+
if (firecrawlResponse.warning) {
|
|
149
|
+
log.extend('warn')('Firecrawl warning: %s', firecrawlResponse.warning);
|
|
150
|
+
}
|
|
111
151
|
|
|
112
152
|
return {
|
|
113
153
|
costTime,
|
|
114
154
|
query: query,
|
|
115
|
-
resultNumbers:
|
|
116
|
-
results:
|
|
155
|
+
resultNumbers: allResults.length,
|
|
156
|
+
results: allResults,
|
|
117
157
|
};
|
|
118
158
|
} catch (error) {
|
|
119
159
|
log.extend('error')('Error parsing Firecrawl response: %o', error);
|
|
@@ -1,35 +1,86 @@
|
|
|
1
|
+
// V2 API Types
|
|
1
2
|
interface FirecrawlScrapeOptions {
|
|
2
|
-
|
|
3
|
+
blockAds?: boolean;
|
|
4
|
+
formats?: string[];
|
|
5
|
+
maxAge?: number;
|
|
6
|
+
onlyMainContent?: boolean;
|
|
7
|
+
removeBase64Images?: boolean;
|
|
3
8
|
}
|
|
4
9
|
|
|
10
|
+
type FirecrawlSource =
|
|
11
|
+
| { location?: string; tbs?: string; type: 'web' }
|
|
12
|
+
| { type: 'images' }
|
|
13
|
+
| { type: 'news' };
|
|
14
|
+
|
|
15
|
+
type FirecrawlCategory = { type: 'github' } | { type: 'research' } | { type: 'pdf' };
|
|
16
|
+
|
|
5
17
|
export interface FirecrawlSearchParameters {
|
|
18
|
+
categories?: FirecrawlCategory[];
|
|
6
19
|
country?: string;
|
|
7
|
-
|
|
20
|
+
ignoreInvalidURLs?: boolean;
|
|
8
21
|
limit?: number;
|
|
22
|
+
location?: string;
|
|
9
23
|
query: string;
|
|
10
24
|
scrapeOptions?: FirecrawlScrapeOptions;
|
|
25
|
+
sources?: FirecrawlSource[];
|
|
11
26
|
tbs?: string;
|
|
12
27
|
timeout?: number;
|
|
13
28
|
}
|
|
14
29
|
|
|
15
30
|
interface FirecrawlMetadata {
|
|
16
31
|
description?: string;
|
|
32
|
+
error?: string | null;
|
|
17
33
|
sourceURL?: string;
|
|
18
34
|
statusCode?: number;
|
|
35
|
+
title?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Web search result
|
|
39
|
+
interface FirecrawlWebResult {
|
|
40
|
+
description: string;
|
|
41
|
+
html?: string | null;
|
|
42
|
+
links?: string[];
|
|
43
|
+
markdown?: string | null;
|
|
44
|
+
metadata?: FirecrawlMetadata;
|
|
45
|
+
rawHtml?: string | null;
|
|
46
|
+
screenshot?: string | null;
|
|
19
47
|
title: string;
|
|
48
|
+
url: string;
|
|
20
49
|
}
|
|
21
50
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
51
|
+
// Image search result
|
|
52
|
+
interface FirecrawlImageResult {
|
|
53
|
+
imageHeight: number;
|
|
54
|
+
imageUrl: string;
|
|
55
|
+
imageWidth: number;
|
|
56
|
+
position: number;
|
|
57
|
+
title: string;
|
|
58
|
+
url: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// News search result
|
|
62
|
+
interface FirecrawlNewsResult {
|
|
63
|
+
date: string;
|
|
64
|
+
html?: string | null;
|
|
65
|
+
imageUrl?: string;
|
|
25
66
|
links?: string[];
|
|
26
|
-
markdown?: string;
|
|
67
|
+
markdown?: string | null;
|
|
27
68
|
metadata?: FirecrawlMetadata;
|
|
28
|
-
|
|
69
|
+
position: number;
|
|
70
|
+
rawHtml?: string | null;
|
|
71
|
+
screenshot?: string | null;
|
|
72
|
+
snippet: string;
|
|
73
|
+
title: string;
|
|
29
74
|
url: string;
|
|
30
75
|
}
|
|
31
76
|
|
|
77
|
+
// V2 Response structure
|
|
32
78
|
export interface FirecrawlResponse {
|
|
33
|
-
data:
|
|
34
|
-
|
|
79
|
+
data: {
|
|
80
|
+
images?: FirecrawlImageResult[];
|
|
81
|
+
news?: FirecrawlNewsResult[];
|
|
82
|
+
web?: FirecrawlWebResult[];
|
|
83
|
+
};
|
|
84
|
+
success: boolean;
|
|
85
|
+
warning?: string | null;
|
|
35
86
|
}
|
|
@@ -26,7 +26,10 @@ beforeEach(async () => {
|
|
|
26
26
|
await initializeDB();
|
|
27
27
|
await clientDB.delete(users);
|
|
28
28
|
|
|
29
|
-
await clientDB
|
|
29
|
+
await clientDB
|
|
30
|
+
.insert(users)
|
|
31
|
+
.values({ id: mockUser.uuid, avatar: 'avatar.png' })
|
|
32
|
+
.onConflictDoNothing();
|
|
30
33
|
await clientDB
|
|
31
34
|
.insert(userSettings)
|
|
32
35
|
.values({ id: mockUser.uuid, general: { themeMode: 'light' } });
|